[Risolto] Range copia e somma

Creare una macro - Scrivere uno script - Usare le API
Rispondi
patel
Volontario attivo
Volontario attivo
Messaggi: 4020
Iscritto il: venerdì 30 aprile 2010, 8:04
Località: Livorno

[Risolto] Range copia e somma

Messaggio 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.
Allegati
SommaCopiaRange.ods
(12.9 KiB) Scaricato 39 volte
Ultima modifica di charlie il giovedì 31 agosto 2023, 16:41, modificato 3 volte in totale.
Motivazione: Sistemato tag [Risolto]
-------------------
Libre Office 7.5.3.2 su Windows 11
allega un file di esempio, guadagnerai tempo tu e lo farai risparmiare a chi ti aiuta
geovign
Messaggi: 217
Iscritto il: domenica 13 gennaio 2019, 11:19
Località: Modena

Re: Range copia e somma

Messaggio 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
Allegati
SommaCopiaRange.ods
(12.73 KiB) Scaricato 26 volte
LibO 7 su LinuxMint 21
patel
Volontario attivo
Volontario attivo
Messaggi: 4020
Iscritto il: venerdì 30 aprile 2010, 8:04
Località: Livorno

Re: Range copia e somma

Messaggio da patel »

Così l'avrei saputo fare anche io, quello che cerco e che non ho precisato nel primo post è risolvere senza cicli.
-------------------
Libre Office 7.5.3.2 su Windows 11
allega un file di esempio, guadagnerai tempo tu e lo farai risparmiare a chi ti aiuta
nickGiard
Messaggi: 65
Iscritto il: lunedì 14 maggio 2012, 22:04

Re: Range copia e somma

Messaggio 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
Nicola con LibreOffice 7.1 (x64) su Windows 11
patel
Volontario attivo
Volontario attivo
Messaggi: 4020
Iscritto il: venerdì 30 aprile 2010, 8:04
Località: Livorno

Re: Range copia e somma

Messaggio 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."
-------------------
Libre Office 7.5.3.2 su Windows 11
allega un file di esempio, guadagnerai tempo tu e lo farai risparmiare a chi ti aiuta
nickGiard
Messaggi: 65
Iscritto il: lunedì 14 maggio 2012, 22:04

Re: Range copia e somma

Messaggio 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
Ultima modifica di charlie il giovedì 31 agosto 2023, 16:41, modificato 1 volta in totale.
Motivazione: Formattato codice
Nicola con LibreOffice 7.1 (x64) su Windows 11
patel
Volontario attivo
Volontario attivo
Messaggi: 4020
Iscritto il: venerdì 30 aprile 2010, 8:04
Località: Livorno

Re: Range copia e somma

Messaggio da patel »

Non si tratta di ritrosia ma solo di curiosità, volevo sapere se era possibile e se mi era sfuggito qualcosa.
-------------------
Libre Office 7.5.3.2 su Windows 11
allega un file di esempio, guadagnerai tempo tu e lo farai risparmiare a chi ti aiuta
geovign
Messaggi: 217
Iscritto il: domenica 13 gennaio 2019, 11:19
Località: Modena

Re: Range copia e somma

Messaggio 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
Ultima modifica di charlie il giovedì 31 agosto 2023, 16:42, modificato 1 volta in totale.
Motivazione: Formattato codice
LibO 7 su LinuxMint 21
Gaetanopr
Volontario
Volontario
Messaggi: 3300
Iscritto il: mercoledì 21 novembre 2012, 20:07

Re: Range copia e somma

Messaggio 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
LibreOffice 7.2.2.2 windows 10
Openoffice 4.1.13 su windows 10
Gaetanopr
Volontario
Volontario
Messaggi: 3300
Iscritto il: mercoledì 21 novembre 2012, 20:07

Re: Range copia e somma

Messaggio 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.

Codice: Seleziona tutto

MSGBOX (oDoc.LastRow("Foglio1"))
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.
LibreOffice 7.2.2.2 windows 10
Openoffice 4.1.13 su windows 10
nickGiard
Messaggi: 65
Iscritto il: lunedì 14 maggio 2012, 22:04

Re: Range copia e somma

Messaggio 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 .
Nicola con LibreOffice 7.1 (x64) su Windows 11
Gaetanopr
Volontario
Volontario
Messaggi: 3300
Iscritto il: mercoledì 21 novembre 2012, 20:07

Re: Range copia e somma

Messaggio 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
LibreOffice 7.2.2.2 windows 10
Openoffice 4.1.13 su windows 10
Gaetanopr
Volontario
Volontario
Messaggi: 3300
Iscritto il: mercoledì 21 novembre 2012, 20:07

Re: Range copia e somma

Messaggio 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 :D ) si può fare senza usare le List comprehension(violazione punto 3) usando il modulo numpy sugli array.
LibreOffice 7.2.2.2 windows 10
Openoffice 4.1.13 su windows 10
nickGiard
Messaggi: 65
Iscritto il: lunedì 14 maggio 2012, 22:04

Re: Range copia e somma

Messaggio 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.
Nicola con LibreOffice 7.1 (x64) su Windows 11
patel
Volontario attivo
Volontario attivo
Messaggi: 4020
Iscritto il: venerdì 30 aprile 2010, 8:04
Località: Livorno

Re: Range copia e somma

Messaggio da patel »

Grazie Gaetano, direi che il quesito è ampiamente risolto.
-------------------
Libre Office 7.5.3.2 su Windows 11
allega un file di esempio, guadagnerai tempo tu e lo farai risparmiare a chi ti aiuta
Gaetanopr
Volontario
Volontario
Messaggi: 3300
Iscritto il: mercoledì 21 novembre 2012, 20:07

Re: Range copia e somma

Messaggio 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.
LibreOffice 7.2.2.2 windows 10
Openoffice 4.1.13 su windows 10
Rispondi