Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Re: dividere il file generato da stampa unione

1,918 views
Skip to first unread message

Giovanni Zezza

unread,
Mar 10, 2009, 12:29:34 PM3/10/09
to
borgodiavalon, nel messaggio
<46486753-3C2D-4228...@microsoft.com>, scriveva:

>ho una serie di file di word relativi ad una lettera tipo creati tramite
>stampa unione ed uniti in nuovo documento, quindi il .doc mi si presenta con
>svariate pagine.
>la mia necessità è quella di estrapolare ogni singola lettera dal .doc
>creato con stampa unione --> copiarla su un nuovo foglio di word (uno per
>lettera) --> salvare il tutto con nome di cui una parte deve essere un codice
>presente nella lettera.
>come si procede?

Credo che sia necessario ricorrere ad un po' di codice vba.

Normalmente la stampa unione produce una sezione per ogni record della
sorgente dati; se il documento principale è costituito da un'unica sezione,
è quindi sufficiente salvare su un documento distinto ogni sezione del
documento unito:

Public Sub separa_sezioni()
Dim sezioni As Sections
Dim sezione As Section
Dim doc_da As Document
Dim doc_a As Document
Dim numero As Integer
Set doc_da = ActiveDocument
Set sezioni = doc_da.Sections
numero = 1
For Each sezione In sezioni
sezione.Range.Copy
Set doc_a = Documents.Add
doc_a.Range.Paste
doc_a.SaveAs (doc_da.Path & "\" & Str(numero) & ".doc")
doc_a.Close
numero = numero + 1
Next
End Sub

Per la questione della costruzione del nome del file, vedi tu ("nome di cui
una parte deve essere un codice presente nella lettera" è un'indicazione un
po' troppo generica per lavorarci sopra). Così come, il codice si limita a
produrre dei file numerati progressivamente.

Se il documento principale è già di più sezioni, allora naturalmente la
procedura non funziona più. Si può cambiare il passo nel ciclo di
salvataggio, selezionando e copiando più sezioni alla volta; oppure si
potrebbe anche pensare di ripetere più volte la stampa unione, una per
record, selezionando con una query il record da stampare.

Ciao.

borgodiavalon

unread,
Mar 11, 2009, 3:49:02 AM3/11/09
to

"Giovanni Zezza" ha scritto:

il codice vba funziona.
il codice presente nella lettera è una sequenza numerica composta da 12
caratteri preceduta dalle parole codice utente. purtroppo ho bisogno di
inserire questo codice nel titolo in quanto il nome del file dovrà poi essere
inserito in una tabella di access per richiamare la lettera generata dalla
routine che mi hai precedentemente postato e tale codice è il riferimento
alla pratica trattata.
per qualsiasi chiarimento sono qui.
grazie

Giovanni Zezza

unread,
Mar 11, 2009, 12:10:38 PM3/11/09
to
borgodiavalon, nel messaggio
<C63DC488-A6FF-422E...@microsoft.com>, scriveva:

>il codice vba funziona.
>il codice presente nella lettera è una sequenza numerica composta da 12
>caratteri preceduta dalle parole codice utente. purtroppo ho bisogno di
>inserire questo codice nel titolo in quanto il nome del file dovrà poi essere
>inserito in una tabella di access per richiamare la lettera generata dalla
>routine che mi hai precedentemente postato e tale codice è il riferimento
>alla pratica trattata.
>per qualsiasi chiarimento sono qui.

Veramente, "vedi tu" significa vedi tu.

Comunque, non è chiaro che cosa sia il "titolo", e dove si debba andare a
prendere il codice utente (ed è anche per questo che ha più senso "vedi
tu", che conosci bene la struttura del documento e dei dati).

Se si tratta (come mi pare probabile) di un campo della stampa unione,
potrebbe valere la pena unire un record alla volta; se no, se il documento
unito è abbastanza regolare da fidarsi, si può ricercare la stringa
all'interno di ogni sezione.

Quando nel ciclo si arriva ad ottenere il range della sezione, si può fare
una ricerca ristretta al range:

....
Dim brano as Range
Dim codice As String
....


For Each sezione In sezioni

Set brano = sezione.Range
brano.Copy
With brano.Find
.Wrap = wdFindStop
.Text = "codice utente"
.....
'eccetera eccetera (vedi tu), fino a potersi copiare il codice
'da qualche parte
...
codice = brano.Range.Text
...
End With


Set doc_a = Documents.Add
doc_a.Range.Paste

doc_a.SaveAs (doc_da.Path & "\" & codice & ".doc")
doc_a.Close
Next
End Sub

Se no, per togliersi un po' dagli stracci:

Public Sub separa_sezioni()
Dim sezioni As Sections
Dim sezione As Section
Dim doc_da As Document
Dim doc_a As Document
Dim numero As Integer

Dim brano As Range
Dim testo
Dim regEx
Dim matches
Dim codice As String
Set regEx = CreateObject("VBScript.RegExp")


Set doc_da = ActiveDocument
Set sezioni = doc_da.Sections

'
regEx.Pattern = "^codice utente\s*(\w+)"
'per l'espressione di ricerca esatta...
'be', vedi tu!
'
regEx.ignoreCase = True
regEx.MultiLine = True


numero = 1
For Each sezione In sezioni

Set brano = sezione.Range
brano.Copy
testo = brano.Text
Set matches = regEx.Execute(testo)
If matches.Count > 0 Then
codice = matches(0).SubMatches(0)
Else
codice = ""
End If


Set doc_a = Documents.Add
doc_a.Range.Paste

If codice <> "" Then
doc_a.SaveAs (doc_da.Path & "\" & codice & ".doc")
Else
doc_a.SaveAs (doc_da.Path & "\numero_" & Str(numero) & ".doc")
End If


doc_a.Close
numero = numero + 1
Next
End Sub

Ciao.

borgodiavalon

unread,
Mar 12, 2009, 10:26:29 AM3/12/09
to

"Giovanni Zezza" ha scritto:

grazie dell'aiuto, ho risolto così per merito della tua preparazione:

Public Sub separa_sezioni()
Dim sezioni As Sections
Dim sezione As Section
Dim doc_da As Document
Dim doc_a As Document
Dim numero As Integer
Dim brano As Range

Dim codice As String
Dim MyMsgBox As String

MyMsgBox = InputBox("inserire data nel formato dd-mm-aa")


Set doc_da = ActiveDocument
Set sezioni = doc_da.Sections

'numero = 1


For Each sezione In sezioni
Set brano = sezione.Range
brano.Copy

sezione.Range.Copy



Set doc_a = Documents.Add
doc_a.Range.Paste

With Selection.Find
.Wrap = wdFindStop
.Execute FindText:="Cod.: "
End With
Selection.MoveStart Unit:=wdCharacter, Count:=6
Selection.MoveRight Unit:=wdCharacter, Count:=12, Extend:=wdExtend

codice = Selection.Text:
'MsgBox codice

doc_a.SaveAs ("c:\lettere_foso\ap-" & codice & "-" & MyMsgBox &
"-aut.doc")


doc_a.Close

'numero = numero + 1
Next
End Sub


sicuramente non è formalmente corretta ma ha raggiunto lo scopo.

grazie ancora.

Giovanni Zezza

unread,
Mar 12, 2009, 11:32:47 AM3/12/09
to
borgodiavalon, nel messaggio
<01AF3892-E003-45F9...@microsoft.com>, scriveva:

> For Each sezione In sezioni
> Set brano = sezione.Range
> brano.Copy
> sezione.Range.Copy

O l'una o l'altra: o copi brano o copi sezione.Range; anche perché la
seconda copia sovrascrive la prima. In questo caso cambia poco perché sono
la stessa cosa, ma è comunque una ripetizione inutile.

Se ti sei preso la briga di fare "Set brano = sezione.Range", a questo
punto io farei "brano.Copy" e basta (ma è anche vero che la variabile brano
nel tuo codice non viene più utilizzata, sicché potresti viceversa
eliminare anche l'assegnazione e fare solo "sezione.Range.Copy").



> Set doc_a = Documents.Add
> doc_a.Range.Paste
>
> With Selection.Find
> .Wrap = wdFindStop
> .Execute FindText:="Cod.: "
> End With

Vabbe', così effettui la ricerca sul nuovo documento... e sperando che non
ci sia alcuna interferenza da parte dell'utente (l'oggetto Selection è roba
sua, in fondo).

Io usavo la variabile di range "brano", per effettuare la ricerca sul
documento originale ed evitare di essere disturbato. La proprietà .Wrap
impostata a wdFindStop garantisce già di per sé che la ricerca sia
ristretta alla sezione corrente. La copia in appunti va effettuata prima
della ricerca, perché la ricerca modifica il range. Per lo stesso motivo,
per stare proprio sicuri, si potrebbe fare "Set brano =
sezione.Range.Duplicate", per sganciare il range di "brano" da quello di
"sezione".

> Selection.MoveStart Unit:=wdCharacter, Count:=6

C'è un sistema più semplice e sicuro per fare questa cosa, utilizzando il
metodo Collapse:

Selection.Collapse wdCollapseEnd

o, usando il Range brano:

brano.Collapse wdCollapseEnd

In questo modo la selezione o il range vengono "collassati" al punto
finale, senza doversi preoccupare di contare i caratteri.
Un altro modo equivalente (e ancora più chiaro) è:

Selection.Start = Selection.End

Ciao.

borgodiavalon

unread,
Mar 13, 2009, 3:26:01 AM3/13/09
to

"Giovanni Zezza" ha scritto:

io ti ringrazio tanto per i consigli, purtroppo ho dovuto sbrigarmela in
quel modo dato che era un lavoro urgente e non sono stato in grado di
seguirli esattamente in quanto su word non avevo mai usato vba, appena potrò
vedro di documentarmi.
mia colpa, avevo sempre visto word solo come una semplice macchina per
scrivere senza provare a vedere quali vere potenzialità possa avere.

0 new messages