Pagina 1 di 1
[Risolto] Macro vba. Si può adattare?
Inviato: domenica 23 settembre 2018, 12:16
da solitariopc
Buongiorno...,
sulla rete ho trovato dopo varie ricerche questa macro scritta in visualbasic per excel, consapevole che non può funzionare in libreoffice per le ovvie ragioni che conosciamo mi rivolgo a Voi per poterla adattare se possibile, allego il file che ho trovato e che funziona in windows XP.
Codice: Seleziona tutto
Option VBASupport 1
Public col(100), r, n, nr As Long, Col2() As Integer
Function comb2(k)
'Variante che lavora con Col2()
col(k) = col(k - 1)
While col(k) < n - r + k
col(k) = col(k) + 1
If k < r Then
comb2 (k + 1)
Else
nr = nr + 1
For i = 1 To r
Col2(nr - 1, i - 1) = col(i)
'Cells(nr, i) = col(i)
Next
End If
Wend
End Function
Sub Anth()
Col2H = Evaluate("FACT(B1)/FACT(B2)/FACT(B1-B2)")
ReDim Col2(Col2H, [B2] - 0)
'Ih = 1: Iv = 1
Foglio1.Range("a4:EA" & Rows.Count).ClearContents
nr = 0
k = 1
r = Cells(2, 2)
n = Cells(1, 2)
[g1] = Timer
comb2 (k)
Range("A4").Resize([M2], [B2]) = Col2
[g2] = Timer
ReDim Col2(1, 1)
End Sub
Una breve spiegazione per capire ciò che fa questa macro: avendo una quantità di numeri (cella B1), in coppie di 2,3,4,5,6, (cella B2)..., le possibili combinazioni sono elencate nella cella M2. Chiedo se si può fare o se esiste un altro modo per ottenere lo stesso risultato. Questo quesito lo rivolgo a chi ha competenze nella scrittura delle macro. Allego File in xls per migliore comprensione.
Grazie a chi concede ascolto; saluti a Voi.
Re: Macro vba. Si può adattare?
Inviato: lunedì 24 settembre 2018, 8:37
da patel
allego il file modificato dove ho sostituito la riga
Range("A4").Resize([M2], [B2]) = Col2
con un ciclo for
Re: Macro vba. Si può adattare?
Inviato: mercoledì 26 settembre 2018, 20:03
da solitariopc
Buonasera, chiedo scusa per il ritardo e rispondo ringraziando Patel per la risposta e il tempo dedicato. Ok, la macro modificata funziona ed è quello che chiedevo nella mia domanda. Se possibile e per favore non me ne voglia, sempre nel solco della domanda di aiuto antecedente ho trovato una macro sempre in vba che funziona allo stesso modo ma va oltre, riesce ad abbinare in combinazioni una tabella di nomi. crede sia possibile adattarla, scriverla in starbasic, le allego il codice e il file in .xls per una rapida visione. Ancora grazie e una buona giornata.
Codice: Seleziona tutto
Rem Attribute VBA_ModuleType=VBAModule
Option VBASupport 1
Public col(100), r, n, nr As Long, Col2() As Variant
Function comb2(k)
'by Anthony47; Variante che lavora con Col2()
col(k) = col(k - 1)
While col(k) < n - r + k
col(k) = col(k) + 1
If k < r Then
comb2 (k + 1)
Else
nr = nr + 1
For I = 1 To r
Col2(nr - 1, I - 1) = col(I)
'Cells(nr, i) = col(i)
Next
End If
Wend
End Function
Sub CombAnth()
'by Anthony47
Dim combArr(), I As Long, J As Long, curCalc
Dim myCombList As String, myMembri As String, myGroup As String, myDest As String
'
'Se M1 e' vuoto si combinano numeri interi da 1 a N
myCombList = "M2" '<<< La cella dove comincia l' elenco delle voci da Combinare
myMembri = "C3" '<<< La cella che contiene il numero di valori da combinare
myGroup = "C4" '<<< La cella che contiene il numero di elementi per ogni gruppo
myDest = "J6" '<<< La cella da dove sara' creato l' elenco combinatorio
'
curCalc = Application.Calculation
Application.Calculation = xlManual
'
If Range(myCombList) <> "" Then
ReDim combArr(1 To 101)
For I = 0 To 100
If Range(myCombList).Offset(0, I) <> "" Then
combArr(I + 1) = Range(myCombList).Offset(0, I).Value
Else
ReDim Preserve combArr(1 To I)
Exit For
End If
Next I
End If
col2h = Evaluate("FACT(" & myMembri & ")/FACT(" & myGroup & ")/FACT(" & myMembri & "-" & myGroup & ")")
ReDim Col2(col2h, Range(myGroup) - 0)
'Ih = 1: Iv = 1
Range(myDest).Resize(Rows.Count - Range(myDest).Row - 1, 5).ClearContents '<<<*** Vedi testo
Range("I8:P8").Resize(Rows.Count - 9, 8).ClearContents
nr = 0
k = 1
r = Range(myGroup)
n = Range(myMembri)
'[g1] = Timer
comb2 (k)
'
If UBound(combArr, 1) < 100 Then
For I = LBound(Col2, 1) To UBound(Col2, 1)
For J = LBound(Col2, 2) To UBound(Col2, 2)
If Not IsEmpty(Col2(I, J)) Then Col2(I, J) = combArr(Col2(I, J))
Next J
Next I
End If
Range("I7:P7").Resize(col2h + 2, 8).FillDown
Range(myDest).Resize(col2h, Range(myGroup)) = Col2
'[g2] = Timer
ReDim Col2(1, 1)
Application.Calculation = curCalc
Calculate
End Sub
P.s. domanda: perché il file che Lei ha modificato è in .xls e non in .ods?
Re: Macro vba. Si può adattare?
Inviato: giovedì 27 settembre 2018, 12:41
da patel
solitariopc ha scritto:Se possibile e per favore non me ne voglia, sempre nel solco della domanda di aiuto antecedente ho trovato una macro sempre in vba che funziona allo stesso modo ma va oltre, riesce ad abbinare in combinazioni una tabella di nomi. crede sia possibile adattarla, scriverla in starbasic...
Troppo complicata, occorrerebbe farsela scrivere dall'autore popolando la tabella con un ciclo invece del metodo array to range.
Queste sono le righe che Starbasic non capisce
Codice: Seleziona tutto
Range("I7:P7").Resize(col2h + 2, 8).FillDown
Range(myDest).Resize(col2h, Range(myGroup)) = Col2
P.s. domanda: perché il file che Lei ha modificato è in .xls e non in .ods?
perché tu mi hai fornito un xls ed io ho modificato le righe incompatibili con starbasic
Re: Macro vba. Si può adattare?
Inviato: venerdì 28 settembre 2018, 22:48
da solitariopc
Patel, la sua risposta conferma i dubbi su quello che avevo pensato e cioè che bisognava mettere mano su molteplici righe se non tutte, la ringrazio ancora per la disponibilità nel rispondere.
Piccola riflessione: chi non utilizza il foglio xls. non potra utilizzare quella soluzione non crede.
Buonaserata e saluti.
Re: Macro vba. Si può adattare?
Inviato: sabato 29 settembre 2018, 10:44
da patel
solitariopc ha scritto:
Piccola riflessione: chi non utilizza il foglio xls. non potra utilizzare quella soluzione non crede.
Non capisco la battuta, OO e LO possono aprire i file xls
Re: Macro vba. Si può adattare?
Inviato: domenica 30 settembre 2018, 0:12
da unlucky83
Codice: Seleziona tutto
REM ***** BASIC *****
option explicit
Function CalculateFactorial( Number )
If Number < 0 Or Number <> Int( Number ) Then
CalculateFactorial = "Invalid number for factorial!"
ElseIf Number = 0 Then
CalculateFactorial = 1
Else
CalculateFactorial = Number * CalculateFactorial( Number - 1 )
Endif
End Function
function combinazioni(membri as long,gruppo as long) as long
combinazioni=CalculateFactorial( membri )/CalculateFactorial( gruppo )/CalculateFactorial( membri-gruppo )
end function
Sub CombAnth()
dim osh as object
Dim combArr(), I As Long, J As Long,m as long,z as long
dim row as long, col as long, row2 as long,col2 as long,col2h as long,rowindex as long
Dim myCombList As String, myMembri As String, myGroup As String, myDest As String
dim nmembri as integer,ngruppi as integer
dim indicirif()
myCombList = "M2" '<<< La cella dove comincia l' elenco delle voci da Combinare
myMembri = "C3" '<<< La cella che contiene il numero di valori da combinare
myGroup = "C4" '<<< La cella che contiene il numero di elementi per ogni gruppo
myDest = "J6" '<<< La cella da dove sara' creato l' elenco combinatorio
osh=thiscomponent.CurrentController.ActiveSheet
row=osh.getcellrangebyname(mycomblist).getrangeaddress().StartRow '
col=osh.getcellrangebyname(mycomblist).getrangeaddress().StartColumn
row2=osh.getcellrangebyname(myDest).getrangeaddress().StartRow '
col2=osh.getcellrangebyname(myDest).getrangeaddress().StartColumn
nMembri=osh.getcellrangebyname( myMembri).value
nGruppi=osh.getcellrangebyname(myGroup).value
i=0
do
If osh.getcellbyposition(col+i,row).string = "" Then exit do
Redim Preserve combarr( 1 to i+1)
combArr(i + 1) = osh.getcellbyposition(col+i,row).string
i=i+1
loop
Redim indicirif(1 to nGruppi)
col2h=combinazioni(nmembri,ngruppi)
osh.getcellrangebyposition(col2,row2,col2+ngruppi-1,10000).clearContents(7)
for j=nGruppi to 1 step -1
for i= lbound( indicirif) to ubound( indicirif)
indicirif(i)=i
next
rowindex=row2
do
if rowindex=col2h+row2 then exit do
for m=indicirif(j) to nMembri -ngruppi+j
z=combinazioni(nMembri-m,nGruppi-j)
for i=0 to z-1
osh.getcellbyposition(col2+j-1,rowindex+i).string=combarr(m)
next
rowindex=rowindex+i
next
indicirif=incremento(indicirif,j,nMembri -ngruppi+j)
loop
next
msgbox "fine"
End Sub
function incremento(indicirif as Variant, j as long,soglia as integer) as variant
dim z as integer
indicirif(j)=indicirif(j)+1
' msgbox j & "#" & soglia & "#" & indicirif(j) & "#" & ubound(indicirif)
if indicirif(j)> soglia then
indicirif=incremento(indicirif,j-1,soglia-1)
else
if j<ubound(indicirif) then
for z=j+1 to ubound(indicirif)
indicirif(z)=indicirif(z-1)+1
next
end if
end if
incremento=indicirif
end function
Ho rifatto le macro utilizzando due funzioni iterative. Ho controllato che funzionasse per membri=10 e gruppi=5. Avendo usato le funzioni iterate dovrebbe andar bene con qualsiasi altra coppia di numeri. Ovviamente il numero delle combinazioni non deve essere maggiore delle righe del foglio e la pulizia del foglio per adesso è impostata fino al rigo 10000
Codice: Seleziona tutto
osh.getcellrangebyposition(col2,row2,col2+ngruppi-1,10000).clearContents(7)
Visto che la macro l'ho fatta in openoffice basic, l'allegato è in formato ods.
Re: Macro vba. Si può adattare?
Inviato: lunedì 1 ottobre 2018, 11:37
da unlucky83
Ho modificato un pò le macro precedenti per renderle più scattanti. La macro principale è Sub Comb()
Codice: Seleziona tutto
REM ***** BASIC *****
option explicit
Function CalculateFactorial( Number )
If Number < 0 Or Number <> Int( Number ) Then
CalculateFactorial = "Invalid number for factorial!"
ElseIf Number = 0 Then
CalculateFactorial = 1
Else
CalculateFactorial = Number * CalculateFactorial( Number - 1 )
Endif
End Function
function combinazioni(membri as long,gruppo as long) as long
combinazioni=CalculateFactorial( membri )/CalculateFactorial( gruppo )/CalculateFactorial( membri-gruppo )
end function
function incremento(indicirif as Variant, j as long,soglia as integer) as variant
dim z as integer
indicirif(j)=indicirif(j)+1
' msgbox j & "#" & soglia & "#" & indicirif(j) & "#" & ubound(indicirif)
if indicirif(j)> soglia then
if j=1 then
exit function
end if
indicirif=incremento(indicirif,j-1,soglia-1)
else
if j<ubound(indicirif) then
for z=j+1 to ubound(indicirif)
indicirif(z)=indicirif(z-1)+1
next
end if
end if
incremento=indicirif
end function
Sub Comb()
dim osh as object
Dim combArr(), I As Long, J As Long,m as long,z as long
dim row as long, col as long, row2 as long,col2 as long,col2h as long,rowindex as long
Dim myCombList As String, myMembri As String, myGroup As String, myDest As String
dim nmembri as integer,ngruppi as integer
dim indicirif()
myCombList = "M2" '<<< La cella dove comincia l' elenco delle voci da Combinare
myMembri = "C3" '<<< La cella che contiene il numero di valori da combinare
myGroup = "C4" '<<< La cella che contiene il numero di elementi per ogni gruppo
myDest = "J6" '<<< La cella da dove sara' creato l' elenco combinatorio
osh=thiscomponent.CurrentController.ActiveSheet
row=osh.getcellrangebyname(mycomblist).getrangeaddress().StartRow '
col=osh.getcellrangebyname(mycomblist).getrangeaddress().StartColumn
row2=osh.getcellrangebyname(myDest).getrangeaddress().StartRow '
col2=osh.getcellrangebyname(myDest).getrangeaddress().StartColumn
nMembri=osh.getcellrangebyname( myMembri).value
nGruppi=osh.getcellrangebyname(myGroup).value
i=0
do
If osh.getcellbyposition(col+i,row).string = "" Then exit do
Redim Preserve combarr( 1 to i+1)
combArr(i + 1) = osh.getcellbyposition(col+i,row).string
i=i+1
loop
Redim indicirif(1 to nGruppi)
for i= lbound( indicirif) to ubound( indicirif)
indicirif(i)=i
next
col2h=combinazioni(nmembri,ngruppi)
osh.getcellrangebyposition(col2,row2,col2+ngruppi-1,10000).clearContents(7)
rowindex=row2
i=0
do
if rowindex+i=col2h+row2 then exit do
for j=1 to nGruppi
osh.getcellbyposition(col2+j-1,rowindex+i).string=combarr(indicirif(j))
next
indicirif=incremento(indicirif,nGruppi,nMembri)
i=i+1
loop
msgbox "fine"
End Sub
Re: Macro vba. Si può adattare?
Inviato: lunedì 1 ottobre 2018, 18:23
da solitariopc
Salve, mi scuso per il ritardo non ho avuto molto tempo a disposizione e sono qui a spiegare l'affermazione di Patel. Signor Patel come lei mi fa notare un file .xls può essere aperto sia con Ooo, che con Liboo, e su questa affermazione taccio per giusta ragione, è vero, ma quello che volevo mettere in evidenza con quella semplice domanda era la possibilità di creare un file originale in .ods completamente creato con libreoffice o openoffice. Chiedo scusa se ho trasmesso un pensiero diverso da quello che volevo dire. Grazie lo stesso anche se non sono stato chiaro nell'esporre il problema.
Unlucky83 il file che Lei ha postato con la macro nuova creata con Basic l'ho provata e fà proprio quello che intendevo esprimere con la nota, Lei ha colto in pieno il senso della (piccola) riflessione, benfatto. Grazie, sembra che funzioni salvo che nel cambio di numero d'accopiate (cella C4)se invece di 5 metto 3 le colonne M ed N della tabella (la 4 e 5) restano scritte per intero non vengono cancellate. Ho risolto con una macro (sempre trovata nel forum) per pulire la tabella prima del ricalcolo; ho inserito una seconda macro per pulire gli elementi in gioco, allego file per conoscenza.
Un saluto a Voi per l'interessamento e l'aiuto. Una buona serata.
P.S. Solo ora ho letto la nuova formulazione per rendere più veloce il lavoro, la provo e le faccio sapere.
Re: Macro vba. Si può adattare?
Inviato: martedì 2 ottobre 2018, 12:15
da unlucky83
Vero
Codice: Seleziona tutto
osh.getcellrangebyposition(col2,row2,col2+ngruppi-1,10000).clearContents(7)
qui la macro dice di pulire le colonne pari al numero indicato in C4. Se il numero massimo dei gruppi è 10 si può modificare in:
Codice: Seleziona tutto
osh.getcellrangebyposition(col2,row2,col2+9,10000).clearContents(7)
, così risparmi un pulsante.
Oppure potresti richiamare la tua macro "Ripulisci_combi" nel codice di Sub CombAnth().
Re: Macro vba. Si può adattare?
Inviato: mercoledì 3 ottobre 2018, 12:25
da solitariopc
Salve unlucky83 buona giornata, ho testato le correzioni che hai scritto e devo dire che è tutto OK, metto risolto. Grazie ancora e Saluti.