View Full Version : [C++] Ordinamento excel
Il mio problema è questo: devo importare un file di excel e ordinarlo in base a più "regole" ad esempio come excel "Ordina per..." "Quindi per..." non so se mi spiego...:p
Importare da excel sono riuscito bene ho dei problemi per l'ordinamento... Come posso fare?
Grazie
PS:
Uso Borland Developer Studio 2006 (utilizzando C++ Builder) e quindi i dati sono in una StringGrid non so se può cambiare qualcosa...:confused:
Purtroppo non credo che tu possa sapere per "cosa" ordina Excel...l'unico modo è riuscirlo a ricavare dai dati...
Prendi tutti i dati e li metti in una struttura (ad esempio un vector di puntatori ad oggetti, un'oggetto per ogni riga del file Excel)...crei una copia di questa struttura (essendo puntatori non ti servirà copiare anche gli oggetti)...
Successivamente applichi il sort della libreria algorithm ordinando per i vari campi e poi confronti l'ordine fino a quando non ottieni lo stesso ordine letto da Excel...
http://cppreference.com/cppalgorithm/sort.html (vedi come si applica il sort usando un algoritmo personalizzato per il confronto)
Purtroppo non credo che tu possa sapere per "cosa" ordina Excel...l'unico modo è riuscirlo a ricavare dai dati...
Prendi tutti i dati e li metti in una struttura (ad esempio un vector di puntatori ad oggetti, un'oggetto per ogni riga del file Excel)...crei una copia di questa struttura (essendo puntatori non ti servirà copiare anche gli oggetti)...
Successivamente applichi il sort della libreria algorithm ordinando per i vari campi e poi confronti l'ordine fino a quando non ottieni lo stesso ordine letto da Excel...
http://cppreference.com/cppalgorithm/sort.html (vedi come si applica il sort usando un algoritmo personalizzato per il confronto)
Il mio problema non è sapere per cosa ordina excel dato che i dati non sono ordinati... Devo ordinarli io...:D
Volevo sapere se per caso si può
1)Utilizzare le funzioni di excel per ordinare i dati.
2)o ordinare facilmente i dati in base a più "regole".
Nel tuo link fa gli esempi di come ordinare un vettore ma in modo standard e quindi non credo mi possa servire a molto... :oink:
Non so forse sono io che non ci capisco molto: è da poco che sono passato al c++ e quindi bo...
Definisci queste "regole"...
Comunque sul link che ti ho postato ti fa vedere come puoi definire tu l'algoritmo che permette di comparare gli elementi del vettore (vedi il terzo parametro di sort, nell'ultimo esempio)
La funzione cmp te la definisci come ti pare e deve ritornare true se lo scambio fra i due elementi deve essere effettuato...ad esempio:
bool cmp( oggetto *a, oggetto *b ) {
int compare = strcmp(a->nome, b->nome);
if(compare > 0)
return true;
if(compare == 0) //sono uguali e valuto un altro campo
if(a->campo > b->campo)
return true;
return false
}
Ad esempio se io ho una tabella con Nome, Cognome, Data di iscrizione, Turno
Come faccio a dirgli di
"Ordinare per Turno" (come farei in excel)
"Quindi per Data di iscrizione"?
Non so se mi spiego
bool cmp( oggetto *a, oggetto *b ) {
return a->getTurno() < b->getTurno();
}
bool cmp( oggetto *a, oggetto *b ) {
return a->getTurno() < b->getTurno();
}
OK così è come compararle ma dato che ci sono molti Nomi con lo stesso Turno devo per forza compararli successivamente per Data di iscrizione se no non li ordina bene... Grazie
Vedi sopra...li ho comparato per due campi...
Scusa ma proprio non capisco tu mi hai scritto come comparare le stinghe e ok ma come fare a ordinare per più cose non capisco:doh:
Per di più in Borland Developer Studio 2006 non c'è la libreria algorithm e non so dove trovarla.:eek:
Per di più in Borland Developer Studio 2006 non c'è la libreria algorithm e non so dove trovarla.:eek:
Rettifico l'ho trovata.
Metti i puntatori agli oggetti nel vettore...e fin qui ci siamo, giusto ?
bool compare(oggetto *a, oggett *b)
{
if(a->getTurno() < b->getTurno()) //turno di a < turno di b e quindi li devo scambiare
return true;
if(a->getTurno() == b->getTurno()) //a e b hanno lo stesso turno, quindi devo controllare una altro campo
if(a->getData() < b->getData()) //il modo in cui fare questo confronto dipende dal formato di data che usi
return true;
else
if(a->getData() == b->getData()) //hanno anche la data uguale ? guardiamo un altro campo
if(a->getNome() < b->getNome()) //anche qui per fare il confronto dipende dal formato di stringa che usi
return true;
return false; //in tutti gli altri casi ritorno false
}
...
vector<oggetto *> v;
...
sort(v.begin(), v.end(), compare);
L'algoritmo di ordinamento lo sai lavora per confronti. Compare si occupa di fare i confronti e sort gli passa due elementi da ordinare. Se compare ritorna true allora gli oggetti a e b nel vettore verranno scambiati...
Metti i puntatori agli oggetti nel vettore...e fin qui ci siamo, giusto ?
bool compare(oggetto *a, oggett *b)
{
if(a->getTurno() < b->getTurno()) //turno di a < turno di b e quindi li devo scambiare
return true;
if(a->getTurno() == b->getTurno()) //a e b hanno lo stesso turno, quindi devo controllare una altro campo
if(a->getData() < b->getData()) //il modo in cui fare questo confronto dipende dal formato di data che usi
return true;
else
if(a->getData() == b->getData()) //hanno anche la data uguale ? guardiamo un altro campo
if(a->getNome() < b->getNome()) //anche qui per fare il confronto dipende dal formato di stringa che usi
return true;
return false; //in tutti gli altri casi ritorno false
}
...
vector<oggetto *> v;
...
sort(v.begin(), v.end(), compare);
L'algoritmo di ordinamento lo sai lavora per confronti. Compare si occupa di fare i confronti e sort gli passa due elementi da ordinare. Se compare ritorna true allora gli oggetti a e b nel vettore verranno scambiati...
Ok in questo modo ho capito però ho ulcuni problemi.
Ho modificato il tuo codice così:
bool cmp(TStrings *a, TStrings *b ) {
if(a->operator [](6).ToInt() < b->operator [](6).ToInt()) //turno di a < turno di b e quindi li devo scambiare
return true;
if(a->operator [](6).ToInt() == b->operator [](6).ToInt()) //a e b hanno lo stesso turno, quindi devo controllare una altro campo
if(StringToDate(a->operator [](5)).operator <(StringToDate(b->operator [](5)))) //il modo in cui fare questo confronto dipende dal formato di data che usi
return true;
else
if(StringToDate(a->operator [](5)).operator ==(StringToDate(b->operator [](5)))) //hanno anche la data uguale ? guardiamo un altro campo
if(a->operator [](4).ToInt() > b->operator [](4).ToInt()) //anche qui per fare il confronto dipende dal formato di stringa che usi
return true;
return false; //in tutti gli altri casi ritorno false
}
Dove TStrings è un vettore di stringhe che rappresenta una riga.
Accedendo ad esempio al suo 6 valore ho il valore del turno di quella riga e così via.
StringToDate è una mia funzione che restituisce la data in formato TDateTime da una stringa
Qui eseguo l'operazione:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TStrings *v[1000] ;
int i;
for (i = 1; i <= StringGrid1->RowCount; i++) {
v[i]=StringGrid1->Rows[i];
}
i=0;
sort(v+2,v + StringGrid1->RowCount,cmp);
for (i = 1; i <= StringGrid1->RowCount; i++) {
StringGrid1->Rows[i]=v[i];
}
}
Faccio partire il sort da 2 perchè la prima riga è vuota e la seconda c'è scritto Nome, Cognome....
Il fatto è che quando l'esegue non ordnina correttamente e perde alcuni risultati dupplicandone altri...:muro:
Come mai? Questo "caso" sta diventando più difficile di quanto credessi...
Nel andare a mettere nel vettore tutte le righe, metti delle strutture dati già interpretate...così eviti anche tutte quelle chiamate dirette agli operatori che non andrebbero fatte...
Che so:
class riga
{
int turno;
int altroIntero; //non so quale significato tu glia abbia
TDateTime data;
TStrings stringhe;
public:
riga(TStrings s);
int getAltroIntero() { return altroIntero; };
int getTurno() { return turno; };
TDateTime getData() { return data; };
TStrings getStringhe() { return stringhe; };
};
riga::riga(TStrings s)
{
stringhe = s;
turno = s[6].toInt();
altroIntero = s[4].toInt();
data = StringToDate(s[5]);
}
In questo modo si semplifica tutto...
Nell'inserimento nel vettore salta la prime due righe e comincia ad inserire dalla terza:
vactor <riga *> v;
v.push_back( new riga(stringhe) );
Ovviamente dopo devi deallocare tutti gli elementi nel vettore...
Il fatto è che non mi permette di crere una variabile TStrings perchè dice che è una classe astratta e quindi posso solo far riferimento alla proprietà di TStringGrid...
Comunque credo che anche con il tuo procedimento avrei gli stessi problemi o no?
Purtroppo qui non ti so aiutare perchè è una classe del framework Borland...hai due alternative: o passi il riferimento o passi il puntatore...
In teoria sì, ma potremmo guardare meglio su cosa "operare"...
Ad esempio potresti mettere una stampa a video degli elementi del vettore per vedere se le conversioni sono fatte in maniera corretta...
Magari c'è qualche problema con la classe TStrings stessa che, visto che ne mantieni il puntatore nel vettore, magari ad ogni estrazione dell'informazione dal file Excel viene sovrascritta...
Scusa se non ti ho risposto ma ho fato un po' di prove e finalmente ce l'ho fatta!!!:D :D :D
Grazie di tutto l'aiuto...
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.