Pagina 1 di 1
[Risolto] Range copia e somma
Inviato: venerdì 28 luglio 2023, 17:31
da patel
Il codice seguente copia il contenuto del range A1:C10 in E1 sommando i contenuti, vedi
https://forum.openoffice.org/it/forum/v ... hp?t=12225
Codice: Seleziona tutto
sub SommaCopiaRange
dim document as object
dim dispatcher as object
document = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
dim args1(0) as new com.sun.star.beans.PropertyValue
args1(0).Name = "ToPoint"
args1(0).Value = "$A$1:$C$10"
dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, args1())
dispatcher.executeDispatch(document, ".uno:Copy", "", 0, Array())
dim args3(0) as new com.sun.star.beans.PropertyValue
args3(0).Name = "ToPoint"
args3(0).Value = "$E$1"
dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, args3())
dim args4(5) as new com.sun.star.beans.PropertyValue
args4(0).Name = "Flags"
args4(0).Value = "VD"
args4(1).Name = "FormulaCommand"
args4(1).Value = 1
args4(2).Name = "SkipEmptyCells"
args4(2).Value = false
args4(3).Name = "Transpose"
args4(3).Value = false
args4(4).Name = "AsLink"
args4(4).Value = false
args4(5).Name = "MoveMode"
args4(5).Value = 4
dispatcher.executeDispatch(document, ".uno:InsertContents", "", 0, args4())
end sub
Mi chiedo come si possa ottenere lo stesso risultato utilizzando il Basic di OO.
Re: Range copia e somma
Inviato: domenica 30 luglio 2023, 10:59
da geovign
Ciao @patel,
secondo me, quanto chiedi, è possibile farlo utilizzando solamente con il codice da te postato.
Il metodo pasteCellRange() faceva in linea di massima quello che chiedi, ma ora è deprecato e non più utilizzabile.
L'unica alternativa è utilizzare getDataArray() e setDataArray() alle due matrici (A1:C10 e E1:G10), facendo la somma dei dati e poi sostituirli nella seconda.
Codice: Seleziona tutto
Sub SommaCopiaRange2
'dichiaro e definisco gli insiemi di celle; questi devono avere le stesse dimensioni
Dim RangeIniziale As Object
Dim RangeDaSommare As Object
RangeIniziale = ThisComponent.Sheets(0).getCellRangeByName("A1:C10")
RangeDaSommare = ThisComponent.Sheets(0).getCellRangeByName("E1:G10")
'dichiaro e definisco le matrici dei dati contenuti nelgli insiemi di celle
Dim arrDatiIniziali() As Variant
Dim arrDatiDaSommare() As Variant
arrDatiIniziali = RangeIniziale.getDataArray() 'matrice dei dati presenti in RangeIniziale
arrDatiDaSommare = RangeDaSommare.getDataArray() 'matrice dei dati presenti in RangeDaSommare
'dichiaro e dimensiono la matrice dei dati da copiare
Dim DatiSommatiDaCopiare() As Variant
DatiSommatiDaCopiare = DimArray(RangeIniziale.Rows.getCount()-1,RangeIniziale.Columns.getCount()-1)
'riempio la matrice DatiSommatiDaCopiare con i dati sommati dei due insiemi di celle
Dim i As Integer
Dim y As Integer
For i = 0 To RangeIniziale.Rows.getCount()-1
For y = 0 To RangeIniziale.Columns.getCount()-1
DatiSommatiDaCopiare(i,y) = arrDatiDaSommare(i)(y) + arrDatiIniziali(i)(y)
'per evitare formattazioni come testo a causa di celle vuote definite come tipo stringa
DatiSommatiDaCopiare(i,y) = CDbl(DatiSommatiDaCopiare(i,y))
Next y
Next i
'definisco l'insieme di celle di destinazione
Dim RangeDestinazione As Object
RangeDestinazione = ThisComponent.Sheets(0).getCellRangeByName("E1:G10")
' inserisco i nuovi dati sommati nell'insieme
RangeDestinazione.setDataArray(DatiSommatiDaCopiare())
End Sub
Attendo comunque altri interventi di utenti pù esperti.
Saluti
Geo
Re: Range copia e somma
Inviato: domenica 30 luglio 2023, 17:18
da patel
Così l'avrei saputo fare anche io, quello che cerco e che non ho precisato nel primo post è risolvere senza cicli.
Re: Range copia e somma
Inviato: sabato 26 agosto 2023, 22:48
da nickGiard
Prova a copiare la prima matrice, e poi vai sulla seconda e pulsante destro incolla speciale Operazione aggiungi, dovresti trovare la somma delle rispettive celle. Penso che si dovrebbe trovare l'equivalente operazione in basic con le API, credo di averti dato un buon spunto.
Saluti, fammi sapere
Re: Range copia e somma
Inviato: domenica 27 agosto 2023, 11:02
da patel
Questo per farlo manualmente o per registrare la macro riportata nel primo post, ma la mia domanda era
"Mi chiedo come si possa ottenere lo stesso risultato utilizzando il Basic di OO."
Re: Range copia e somma
Inviato: domenica 27 agosto 2023, 19:25
da nickGiard
Bene, andando in cerca nel testo bibbia di Andrew PitonYak
1) Use the copyRange(CellAddress, CellRangeAddress) method to copy a range of cells to the location
Questo metodo non prevede operazioni col range di destinazione.
2) Usi XSheetPastable pasteCellRange() dove PasteOperation ADD old and new values are added.
Questo metodo sembrerebbe essere utile al nostro scopo, ma risulterebbe DEPRECATO (come già detto).
Se è stato DEPRECATO forse qualche ragione c'era, probabilmente sul Tipo dei Valori che non poteva essere controllato a priori per evitare errori, sebbene in Incolla Speciale manuale è previsto.
A questo punto non capisco la ritrosia ad usare un doppio ciclo sui Valori del DataArray dei due range, che mi sembra apprezzabilmente veloce
Codice: Seleziona tutto
Dim aaOri : aaOri = rgOri.DataArray
Dim aaDest : aaDest = rgDest .DataArray
Dim r%, c%
For r = 0 To UBound( aaOri )
For c = 0 To UBound( aaOri(0)
If TypeName( aaOri(r)(c)) = "String" Then GoTo NexC
If TypeName( aaDest(r)(c)) = "String" Then GoTo NexC
aaDest(r)(c) = aaDest(r)(c) + aaOri(r)(c) ' o qualsiasi altra operazione
Next
NexC:
Next
Sinceramente mi sembra una soluzione elegante, visti gli strumenti del Basic
Re: Range copia e somma
Inviato: lunedì 28 agosto 2023, 8:13
da patel
Non si tratta di ritrosia ma solo di curiosità, volevo sapere se era possibile e se mi era sfuggito qualcosa.
Re: Range copia e somma
Inviato: martedì 29 agosto 2023, 7:39
da geovign
Una soluzione possibile, è utilizzare VBA:
Codice: Seleziona tutto
Sheets("NomeFoglio").Select
Range("RangeDiOrigine").Select
Selection.Copy
Range("CellaDiDestinazione").Select
Selection.PasteSpecial Paste:=xlAll, Operation:=xlAdd, SkipBlanks:=False, Transpose:=False
Non è una soluzione "ottimale" , ma è quanto più si avvicina, secondo me, alla tua richiesta.
Saluti
Geo
Re: Range copia e somma
Inviato: martedì 29 agosto 2023, 10:18
da Gaetanopr
geovign ha scritto: ↑martedì 29 agosto 2023, 7:39
Una soluzione possibile, è utilizzare VBA:
Non è una soluzione "ottimale" , ma è quanto più si avvicina, secondo me, alla tua richiesta.
L'utilizzo di un linguaggio diverso è la soluzione che più si ci allontana, le condizioni sono 3:
1) USO ESCLUSIVO DEL BASIC di OO
2) MACRO NON REGISTRATA, NIENTE DISPATCH
3) SENZA USARE CICLI
Saluti
Re: Range copia e somma
Inviato: martedì 29 agosto 2023, 17:36
da Gaetanopr
Esiste il metodo RunCommand della libreria ScriptForge tramite il quale è possibile richiamare qualsiasi comando UNO.
Codice: Seleziona tutto
sub SommaRange
GlobalScope.BasicLibraries.loadLibrary("ScriptForge")
Set oDoc = CreateScriptService("Calc", ThisComponent)
oDoc.RunCommand( ".uno:GoToCell", "ToPoint", "$A$1:$C$10" )
oDoc.RunCommand(".uno:Copy")
oDoc.RunCommand( ".uno:GoToCell", "ToPoint", "$E$1")
oDoc.RunCommand(".uno:InsertContents", "FormulaCommand", 1, "MoveMode", 4)
Set oDoc = oDoc.Dispose()
End Sub
Questa libreria presenta una moltitudine di propietà e metodi molto utili, ad esempio per trovare l'ultima cella utilizzata basta questa semplice istruzione, indicando come parametro il nome del foglio tra virgolette.
Viene restituito il numero della riga non l'indice, quindi se l'ultima riga occupata è A50 viene restituito 50 e non 49(l'indice di riga)
Naturalmente bisogna caricare la libreria come fatto sopra.
Re: Range copia e somma
Inviato: martedì 29 agosto 2023, 21:16
da nickGiard
Le condizioni poste da Gaetanopr sono veramente stringenti.
Facendo una ricerca nelle API non si trova alcun metodo che contenga la parola paste, per cui non credo che si possa risolvere direttamente con un metodo diretto in basic.
Si potrebbe pensare ad una funzione Python, che comunque incorpora un ciclo nella List comprehension.
In merito alle librerie ScriptForge, sono sicuramente un esempio molto apprezzabile di programmazione avanzata in Basic, ma che spesso sono un contorto wrapper a funzioni che potrebbero essere usate direttamente; ad esempio i RunCommand indicati da Gaetanopr non sono altro che istruzioni oDispatch.executeDispatch(_Frame, ".uno:" & Command, "", 0, Array()), e quindi non rientrano nella condizione 2) MACRO NON REGISTRATA, NIENTE DISPATCH .
Re: Range copia e somma
Inviato: martedì 29 agosto 2023, 21:44
da Gaetanopr
I RunCommand non sono propriamente dei Dispatch, fanno come i Dispatch riferimento ai comandi Uno, ad ogni modo ti allego una soluzione che soddisfa i tre requisiti(anche se continuo a preferire la macro registrata o il runcommand)
Codice: Seleziona tutto
Sub Main
Doc = ThisComponent
sh = Doc.Sheets(0)
sh.getCellRangeByName("K1:M10").ArrayFormula = "=(A1:C10 + E1:G10)"
arr = sh.getcellrangebyname("K1:M10").GetDataArray
sh.getcellrangebyname("E1:G10").setdataarray(arr)
sh.getCellRangeByName("K1:M10").ClearContents(16)
End Sub
Re: Range copia e somma
Inviato: mercoledì 30 agosto 2023, 11:21
da Gaetanopr
Sul metodo PasteCellRange già si era parlato sul forum inglese e già dal 2014 era deprecato
https://forum.openoffice.org/en/forum/v ... eCellRange
nickGiard ha scritto: ↑martedì 29 agosto 2023, 21:16
Si potrebbe pensare ad una funzione Python, che comunque incorpora un ciclo nella List comprehension.
Dato che hai tirato in ballo il python(violazione punto 1
) si può fare senza usare le List comprehension(violazione punto 3) usando il modulo numpy sugli array.
Re: Range copia e somma
Inviato: mercoledì 30 agosto 2023, 17:46
da nickGiard
Gaetanopr grazie per la bellissima soluzione dell' ArrayFormula , da me mai usata se non recentemente per una serie di formule in colonna con riferimento a quelle affiancate, scoprendo ora un approfondimento nel cap. 15.4.10. Array formulas di Andrew PitonYak e che andrò a studiare attentamente.
Purtroppo il modulo numpy non fa parte del corredo standard di LO, mi hanno spiegato che essendo enorme andrebbe ad appesantire oltremodo LO.
Re: Range copia e somma
Inviato: giovedì 31 agosto 2023, 9:40
da patel
Grazie Gaetano, direi che il quesito è ampiamente risolto.
Re: Range copia e somma
Inviato: sabato 9 settembre 2023, 12:25
da Gaetanopr
nickGiard ha scritto: ↑mercoledì 30 agosto 2023, 17:46
Purtroppo il modulo numpy non fa parte del corredo standard di LO, mi hanno spiegato che essendo enorme andrebbe ad appesantire oltremodo LO.
Non fa parte del corredo standard di Python in genere non solo di LO, la peculiarità di Python è proprio questa, cioè quella di poter attingere a migliaia di librerie già con incluse funzioni per qualsiasi necessità, per quanto riguarda la pesantezza posso dirti che ne scaricate diverse su LO e mi ha velocizzato dei processi in maniera sorprendente, cose che con il Basic mi sognavo.