Come posso fare a confrontare 2 colonne di dati presenti in 2 diversi
files Calc ed ottenere la lista degli eventuali valori ripetuti tra le
2 colonne. Premetto che nelle varie caselle sono inserite solo parole,
non valori numerici. Presumo sia necessaria una macro...
Esempio.
Colonna A file 1:
pippo
pluto
paperino
topolino
paperoga
Colonna A file 2:
minnie
topolino
paperina
paperone
pluto
etabeta
vorrei che la macro mi restituisse l'elenco dei valori ripetuti,
meglio se in file di testo, che nella fattispecie sono:
pluto
topolino
grazie, Tommy
Com una macro si puo' fare facilmente.
I dati sono ordinati?
I dati sono eventualmente ordinabili?
Quante decine di migliaia sono le righe dei dati?
Infine, dove deve essere messo il risultato?
sono colonne che contengono parole e non numeri come nell'esempio di
prima.
l'ordine delle parole è alfabetico e sono già ordinate dalla A alla Z
ogni colonna contiene circa 65000 caselle
l'elenco delle parole ripetute può essere messo in un txt, in un file
di Writer o in una colonna di un nuovo file Calc,
non ho particolari preferenze, va bene quella che comporta meno
difficoltà di programmazione
Se le parole sono gia' ordinate, la cosa e' relativamente semplice e
sicuramente veloce.
Si prendono due indici, uno per la prima colonna e uno per la seconda
e si confrontano le due parole.
Se sono uguali si inserisce la parola nell'elenco delle parole trovate
e si incrementano entrambi gli indici.
Se non sono uguali, una delle due e' maggiore dell'altra.
Si incrementa quindi solo l'indice della parola minore e si ripete il
ciclo finche' uno dei due indici non raggiunge la fine.
Avendo gia' dei fogli elettronici sottomano, il posto piu' comodo dove
andare a scrivere il risultato e' una colonna di un foglio
elettronico, cosi' non si devono aprire files con tutte le
problematiche annesse e connesse.
Pensi di riuscire a produrla autonomamente?
Il numero di riga della cella e' un indice (se i dati sono messi in
colonna).
Non so se hai già risolto, altrimenti prova la seguente macro come
punto di partenza. Va controllata e verificata nei risultati. Non so
come si comporta con molti dati. Se è giusta forse va ottimizzata, ci
sono alcune cose che non conosco bene. Insomma prendila con le
molle ;-)
La lanci da uno dei due file e l'altro può anche essere chiuso. Il
file di testo di uscita dovrebbe essere generato al momento. Inserisci
i nomi dei file e i relativi percorsi.
Non rispondo di eventuali danni (uomo avvisato ...)
Sub FindEqualItems
Dim i , j As Integer
i = 0 'Indice scansione primo file
j = 0 'Indice scansione secondo file
oActiveSheet = ThisComponent.CurrentController.ActiveSheet
Dim Url as String
Url = convertToUrl("C:\percorso_del_secondo_file\file2.ods")
Dim Doc
Dim secondFileSheet
Doc = starDeskTop.loadComponentFromUrl (Url, "_blank", 0, Array())
secondFileSheet = Doc.Sheets.getByName("Foglio1")
Filename = "C:\percorso_del_file_dei_risultati\file.txt"
FileNo = FreeFile
Open Filename For Append As #FileNo
Do While (oActiveSheet.getCellByPosition(0,i).getFormula() <> "" AND _
secondFileSheet.getCellByPosition(0,j).getFormula() <> "")
firstItem = oActiveSheet.getCellByPosition(0,i).getFormula()
secondItem = secondFileSheet.getCellByPosition(0,j).getFormula()
if firstItem < secondItem then
i=i+1
elseif firstItem > secondItem then
j=j+1
else
Print #FileNo, firstItem
i=i+1
j=j+1
end if
loop
Close #FileNo
End Sub
P.S. i dati sui due file devono essere ordinati.
Attenzione, che quella macro presuppone che i dati siano nella colonna
A di entrambi i files.
p.s. chiedo all'autore della macro: perche' getFormula() ?
Io avrei preso il dato come string.
Perché sono un niubbo :-)
Ho adattato una macro che già avevo e che serviva a tutt'altro.
Tommy, sostituisci nella macro getFormula() con getString()
Avevo avvisato di prenderla con le molle.
Grazie per la correzione. Se c'è dell'altro, spara pure. ;-)
deve esserci un errore di sintassi della macro in questo pezzo di
codice (ho già sostituito getFormula con getString):
Do While (oActiveSheet.getCellByPosition(0,i).getString() <> "" AND _
secondFileSheet.getCellByPosition(0,j).getString() <> "")
firstItem = oActiveSheet.getCellByPosition(0,i).getString()
secondItem = secondFileSheet.getCellByPosition(0,j).getString()
se la lancio così mi da errore di parentesi sulla prima riga a livello
di "Do While"
immagino che le prime 2 righe debbano essere unite, ma se metto:
Do While (oActiveSheet.getCellByPosition(0,i).getString() <> "" AND _
secondFileSheet.getCellByPosition(0,j).getString() <> "")
ricevo ancora errore di parentesi sul trattino basso...
modificando ulteriormente, togliendo lo spazio tra AND e il trattino
basso:
Do While (oActiveSheet.getCellByPosition(0,i).getString() <> ""
AND_secondFileSheet.getCellByPosition(0,j).getString() <> "")
la macro parte, carica il 2° file ma ri riblocca sulla riga precedente
dicendo:
Errore di runtime BASIC. variabile dell'oggetto non impostata.
avete idee di dove stia l'inghippo?
Sub TrovaRipetizioni
Dim i , j As Integer
i = 0 'Indice scansione primo file
j = 0 'Indice scansione secondo file
oActiveSheet = ThisComponent.CurrentController.ActiveSheet
Dim Url as String
Url = convertToUrl("C:\Download Parking\testOOO\acor_it-CH.ods")
Dim Doc
Dim secondFileSheet
Doc = starDeskTop.loadComponentFromUrl (Url, "_blank", 0, Array())
secondFileSheet = Doc.Sheets.getByName("Foglio1")
Filename = "C:\Download Parking\testOOO\ripetizioni.txt"
FileNo = FreeFile
Open Filename For Append As #FileNo
Do While (oActiveSheet.getCellByPosition(0,i).getString() <> "" AND
_secondFileSheet.getCellByPosition(0,j).getString() <> "")
firstItem = oActiveSheet.getCellByPosition(0,i).getString()
secondItem = secondFileSheet.getCellByPosition(0,j).getString()
if firstItem < secondItem then
> Do While (oActiveSheet.getCellByPosition(0,i).getString() <> "" AND
> _secondFileSheet.getCellByPosition(0,j).getString() <> "")
Qui è stato riadattato male :-)
L'underscore deve essere nella linea sopra e non ci deve essere alcuno
spazio dopo.
Quelle due linee in realtà sono una linea unica e, a quanto ne so io,
ma non ho approfondito, l'underscore preceduto da uno spazio e seguito
da niente (a capo) è l'unico modo per fare stare del codice su più
righe altrimenti nel Basic la fine istruzione è individuata dalla fine
della riga
Come l'hai posto tu sono due righe diverse e nella prima manca la
parentesi di chiusura della condizione Do While (da cui l'errore).
Alternativamente puoi mettere tutto su un'unica linea.
Comunque puoi provare anche la seguente che è un po' più ordinata
della precedente e chiama meno volte getCellByPosition (e come
curiosità mi potresti dire se è anche un po' più veloce visto che non
ho provato con molti elementi):
Sub FindEqualItems
Dim i, j As Integer
i = 0 'Indice scansione primo intervallo
j = 0 'Indice scansione secondo intervallo
Dim firstItem, secondItem as String
Dim oActiveSheet
oActiveSheet = ThisComponent.CurrentController.ActiveSheet
Dim Url as String
Url = convertToUrl("C:\percorso_secondo_file\file2.ods")
Dim Doc
Dim secondFileSheet
Doc = starDeskTop.loadComponentFromUrl (Url, "_blank", 0, Array())
secondFileSheet = Doc.Sheets.getByName("Foglio1")
Dim Filename
Filename = "C:\percorso_file_risultati\file.txt"
FileNo = FreeFile
Open Filename For Append As #FileNo
firstItem = oActiveSheet.getCellByPosition(0,i).getString()
secondItem = secondFileSheet.getCellByPosition(0,j).getString()
Do While (firstItem <> "" AND secondItem <> "")
if firstItem < secondItem then
i=i+1
elseif firstItem > secondItem then
j=j+1
else
Print #FileNo, firstItem
i=i+1
j=j+1
end if
firstItem = oActiveSheet.getCellByPosition(0,i).getString()
secondItem = secondFileSheet.getCellByPosition(0,j).getString()
loop
Close #FileNo
End Sub
Si potrebbe fare ancora meglio aggiornando firstItem e secondItem solo
quando cambia "i" oppure "j", ma non credo ci sia un problema di
prestazioni per l'utilizzo che se ne deve fare ;-)
So che l'accesso agli elementi del foglio di calcolo è una cosa che
rallenta il codice, magari Roberto Montaruli può dire qualche cosa a
riguardo .
> So che l'accesso agli elementi del foglio di calcolo è una cosa che
> rallenta il codice, magari Roberto Montaruli può dire qualche cosa a
> riguardo .
Parliamo di quante righe?
E di quante esecuzioni al giorno di questa macro?
Io generalmente preferisco avere un codice chiaro, leggibile e
facilmente modificabile, piuttosto che un codice estremamente
ottimizzato che diventa poi poco leggibile, quando scrivo le macro.
> Parliamo di quante righe?
> E di quante esecuzioni al giorno di questa macro?
>
Il discorso è in generale perché per l'uso che ne deve fare Tommy
penso che non ci sia un problema in tale senso. Mi sembra di capire
che dovrebbe usarla una volta sola oppure una volta ogni tanto.
Come numero di righe si parlava di due file con 65000 elementi
ciascuno (1 colonna x 65000 righe).
la macro funziona su file test con poche caselle
se lanciato sui 2 file grossi, invece ricevo errore sulla riga:
j=j+1
Valore o tipo di dati non ammesso.
Overflow
che significa?
controllando il file txt noto che alcuni valori sono stati copiati
(ripetizioni dalla A alla I) mentre le altre (dalla J alla Z)
evidentemente non sono state inserite a causa del blocco della macro
Giusto! 65000 elementi superano il limite del tipo "integer" (numero
intero compreso tra -32768 e 32767) quindi "i" e "j" devono essere
definiti come tipo "long" (valori interi compresi tra –2147483648 e
2147483647).
Nella macro sostituisci la riga
Dim i, j As Integer
con la seguente:
Dim i, j As Long
grazie