Copiare intestazioni di tabelle Word (uno sfizio, però istruttivo)
Di ritorno dalle vacanze (e da rogne infinite) propongo al visitatore una varietà di soluzioni a un problemino sollevato da un tal Rick. Come dirò al termine, più che altro è uno sfizio di cui non trovo valore pratico, tuttavia è una curiosità che chiarisce il trattamento di tabelle in Word, ergo ha una certa valenza se non altro didattica.
Ma ecco il quesito del summenzionato Rick. Si abbiano in un documento Word due tabelle di pari numero di colonne come le seguenti:
TABELLA 1
|
Prodotto |
Prezzo |
Quantità |
Importo |
Sconto |
Netto |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TABELLA 2
|
Questo |
Quello |
Eccetera... |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Si desidera, nel modo più automatico possibile, che la prima riga di intestazioni della Tabella 1 venga riprodotta nella Tabella 2. Va subito premesso che in Word l’unica possibilità è data da una macro ad hoc: ci si tolga dalla testa quel che invece offre Excel, con formule tipo =$A1 o con macro d’evento, tipicamente quella dell’evento Change che si scatena quando l’utente modifica qualcosa. Word è assai povero di eventi e non c’è nulla del genere.
Ecco perché in apertura ho parlato di “sfizio”: specie se l’operazione va fatta una tantum il gioco non vale la candela, essendo più semplice un copia/incolla fatto a manina. Comunque ecco le varie trovate.
Soluzione 1
Ottenuta nella fretta di rispondere a caldo all’impaziente soggetto:
Sub CopiaIntest()
For i = 1 To Tables(1).Columns.Count
Tables(1).Rows(1).Cells(i).Select
DatoCella = Selection
DatoCella = Left(DatoCella, Len(DatoCella) - 2)
Tables(2).Rows(1).Cells(i).Select
Selection = DatoCella
Next
End Sub
Premesso che Tables(1) e Tables(2) sono le nostre due tabelle e che Tables(1).Rows(1).Cells sono le celle dalla prima intestazione, mentre ovviamente la riga intestataria dell’altra tabella è data dalla stessa espressione ma con Tables(2) al posto di Tables(1).
Il procedimento consiste in un loop che spazzola le celle della prima intestazione (il cui numero è Tables(1).Columns.Count) selezionando ciascuna, mediante Tables(1).Rows(1).Cells(i).Select, quindi l’oggetto Selection, basilare in Word, è registrato in DatoCella, con successiva “cura” che ne toglie gli ultimi due caratteri. Si passa poi a selezionare l’i-esima cella della prima riga della seconda tabella, rendendo infine Selection = DatoCella.
Il motivo della predetta cura? Come si constata col debug passo passo (tasto F8) la selezione, verbigrazia, della prima cella di Tabella 1 non è solo “Prodotto” ma è seguito da un Carriage Return e da un pallino (Ascii 7), il che fa parte della codifica delle celle di una tabella Word (per distinguerle, penso). Si provi infatti a eliminare l’istruzione DatoCella = Left(DatoCella, Len(DatoCella) - 2): si constaterà che nella cella destinataria compare un CR.
Variante, con sorprese
Sub CopiaIntestBIS()
For i = 1 To Tables(1).Columns.Count
Tables(1).Rows(1).Cells(i).Select
Selection.Copy
Tables(2).Rows(1).Cells(i).Select
Selection.Paste
Next
End Sub
Qui ho rinunciato alla variabile-punte DatoCella sfruttando il metodo Copy della Selection relativa alla cella i-esima per poi applicare il metodo Paste alla Selection della corrispondente cella della Tabella 2. Stavolta, ecco la sorpresa!, l’istruzione “curativa” è per così dire indifferente: il risultato è corretto sia che venga o non venga applicata. Un’altra differenza che si constata è che mentre CopiaInTest lascia immutati sia gli sfondi che gli attributi delle celle destinatarie CopiaIntestBIS conserva solo gli sfondi ma, ad esempio, il grassetto delle celle di Tabella 1 viene acquisito dalle corrispettive di Tabella 2 (che non l’aveva).
Nota Di queste particolarità non ho sinceramente avuto modo né voglia di farmi una ragione. Lo faccia chi può, comunque pragmaticamente non c’è che da prenderne atto..
Seconda soluzione
I procedimenti fin qui esaminati, agiscono per successive selezioni di celle (e quando terminano si ha è selezionata l’ultima cella della seconda tabella). Quelli “più audaci” che andiamo a vedere agiscono invece “a distanza”, ossia mantenendo la selezione corrente. Per constatarlo si ponga il cursore in un punto qualsiasi del documento, magari fuori delle tabelle.
Ma ecco la prima Sub “audace”:
Sub CopiaIntestaz()
For i = 1 To Tables(1).Columns.Count
Tables(1).Rows(1).Cells(i).Range.Copy
Tables(2).Rows(1).Cells(i).Range.Paste
Next
End Sub
Qui, come nelle altre soluzioni che mostreremo, si ricorre alla basilare proprietà Range. Difficile definirla in due parole, dirò solo che restituisce il dato di un certo oggetto Word. In tal modo l’applicazione dei metodi Copy e Paste funziona correttamente e, quel che è più bello, agisce “a distanza”! E con le non del tutto attese modalità del caso precedente.
Terza soluzione
Ma perché, ci siamo subito detti, operare cella per cella? Proviamo allora con copia / incolla sulle intere prime righe. Ed ecco il primo tentativo in tale direzione, basato sul fatto che anche a un oggetto Row si applicano Copy e Paste:
Sub CopiaIntestazioniOLD()
'Dio sa perché viene AGGIUNTA una riga, con
'formattazioni identiche a quelle della tabella 1
Tables(1).Rows(1).Range.Copy
Tables(2).Rows(1).Range.Paste
End Sub
Tutto OK? Mica poi tanto. Infatti viene mantenuta l’azione “a distanza”, ma si presenta l’ennesima sorpresina:
TABELLA 2
|
Prodotto |
Prezzo |
Quantità |
Importo |
Sconto |
Netto |
|
Questo |
Quello |
Eccetera... |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ovvero stavolta la prima riga di Tabella 1 viene inserita prima di quella della Tabella 2. Ancora una volta non so darne spiegazione e faccio appello ai più esperti, se riescono a trovare una pezza migliore di quella che infine propongo, basata sulla cancellazione della riga 1 di Tabella 2, prima del Paste.
Sub CopiaIntestazioni()
'Funziona! sempre copiando anche i formati
Tables(1).Rows(1).Range.Copy
Tables(2).Rows(1).Delete
Tables(2).Rows(1).Range.Paste
End Sub
Un’ultima annotazione (espressa dai commenti inseriti): stavolta la copia dei formati dell’intestazione di Tabella 1 è totale, riguarda sia i font che gli sfondi. Perché mai? A noi pigri non resta che prenderne atto.
?>