La settimana scorsa, durante un corso di Excel per una azienda del Luganese, mi hanno raccontato una brutta storia. Uno dei lavori ricorrenti più lunghi, ingrati e noiosi affidati in azienda ad alcuni allievi era questo: data una tabella di ordini riempita dal cliente e simile a questa:
ottenere un elenco di dati simile a questo:
La prima domanda, ovviamente, è stata “Perché? Ma soprattutto, perché?” La dura risposta: “Perché il cliente vuole così, e il cliente ha sempre ragione”. Questo restringe molto il campo delle possibili soluzioni, ma almeno si può fare una bella macro. Siccome non c’è stato tempo durante il corso, mi ci sono divertito oggi e ho messo insieme una soluzione “quick & dirty” che farà storcere il naso a tutti i programmatori (io non lo sono), ma che funziona per qualsiasi tabella di qualsiasi dimensione, purché si parta con una cella attiva dentro la tabella da svolgere. Il file di esempio (47KB formato Excel 2003) è dalla tabella alla lista, e il codice è questo:
Sub Tabella_Elenco()
‘
‘ Prende una tabella da un foglio
‘ e la trasforma in un elenco in un altro foglio
‘
On Error Resume Next
Application.ScreenUpdating = FalseDim MioFoglio As Worksheet
Dim MiaTabella As Range
Dim Etichette As Range
Dim colcnt As Integer
Dim rowcnt As Integer‘ Definisco le variabili e il foglio di destinazione
‘ con le etichetteSet MioFoglio = ActiveSheet
Set MiaTabella = ActiveSheet.Cells(1, 1).CurrentRegion
colcnt = MiaTabella.Columns.Count
rowcnt = MiaTabella.Rows.Count
Set Etichette = MiaTabella.Range(Cells(1, 2), Cells(1, colcnt))
N = 0Sheets.Add.Name = “Destinazione”
With ActiveWorkbook.Names
.Add Name:=”Prodotto”, RefersTo:=”=Destinazione!A1″
.Add Name:=”Taglia”, RefersTo:=”=Destinazione!B1″
.Add Name:=”Quantità”, RefersTo:=”=Destinazione!C1″
End With
Range(“Prodotto”).FormulaR1C1 = “Prodotto”
Range(“Taglia”).FormulaR1C1 = “Taglia”
Range(“Quantità”).FormulaR1C1 = “Quantità”‘ Copio e incollo in modo diverso per la prima riga
While N < rowcnt – 1
Application.CutCopyMode = False
MiaTabella.Cells(N + 2, 1).Copy
Application.Goto Reference:=”Prodotto”If N = 0 Then
Range(“Prodotto”).Offset(1, 0).Range(“A1”).SelectElse
Range(“Prodotto”).End(xlDown).Offset(1, 0).Range(“A1″).Select
End IfSelection.Resize(Selection.Rows.Count + colcnt – 2, Selection.Columns.Count).Select
ActiveSheet.PasteApplication.CutCopyMode = False
Etichette.Copy
Application.Goto Reference:=”Taglia”If N = 0 Then
Range(“Taglia”).Offset(1, 0).Range(“A1”).PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=True
Else
Range(“Taglia”).End(xlDown).Select
ActiveCell.Offset(1, 0).Range(“A1″).PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=True
End IfApplication.CutCopyMode = False
MioFoglio.Select
MiaTabella.Range(Cells(N + 2, 2), Cells(N + 2, colcnt)).Copy
Application.Goto Reference:=”Quantità”If N = 0 Then
Range(“Quantità”).Offset(1, 0).Range(“A1”).PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=True
Else
Range(“Quantità”).End(xlDown).Select
ActiveCell.Offset(1, 0).Range(“A1”).PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=True
End IfN = N + 1
Wend
Application.CutCopyMode = False
Range(“A1”).Select
Application.ScreenUpdating = TrueEnd Sub
Buon divertimento. Molto volentieri accetto critiche, pomodori e suggerimenti.
Sono certo che ci avevi già pensato, però se si accetta di aggiornare manualmente la combinazione di taglia e prodotto (ragionevole perché è la lista che serve alla fine), il risultato si può ottenere senza vba con un doppio cerca.vert o con l’uso della funzione matr.somma.prodotto.
ho commentato di là
This comment was originally posted on FriendFeed
Massimo, giusto. Le linee di prodotto sono però davvero molte, e ogni volta arriva una nuova tabella con un diverso numero di righe e colonne. Per questo si è pensato a una macro invece che a una soluzione calcolata.
MarcoScan (i trackback sono una delle piacevoli sorprese di questa nuova casa): il tuo codice in R è elegantissimo, complimenti. Ma tieni presente che io non sono un programmatore e che sicuramente un esperto di VB farebbe molto meglio di me 🙂
Un’altra possibilità è probabilmentee quella di fare parsing direttamente sull’XML della tabella. Se qualcuno ha esperienze in merito, sarei curioso di conoscerle.
visto, grazie Massimo
This comment was originally posted on FriendFeed
visto, grazie
This comment was originally posted on FriendFeed
ma la tabella arriva in xml o parli dell’xml del formato di excel?
Parlo dell’XML del formato di Excel 2007
Ti ho mandato via mail una soluzione con sole formule.
Tipico esempio di end user development
http://en.wikipedia.org/wiki/End-user_development
http://www.youtube.com/watch?v=MxpjGZinies
http://lambda-the-ultimate.org/node/3821
In particolare sottoscrivo in pieno il post http://www.marcoscan.com/2010/05/lelefante-e-la-farfalla-interpretata-da-excel-e-r.html
Che conferma pienamente quello che dice Allen Cypher: “Allen mentions the practical issues of knowing when to use what tool, and that novice users struggle with finding the right tool for the right job. ”
Capisco che conoscendo Excel si tenti di fare tutto in Excel, ma piantare chiodi con una livella non e’ la strada giusta.
@ErMejo: scusa ma il tuo commento conteneva più di un link ed è finito in moderazione. Ma grazie per averli messi, sono molto interessanti.