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.

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.

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 :D ) 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.