Ich denke mir halt, das könnte man aber auch innerhalb von
Word mit einem Makro „erledigen“. Die nötigen zwei
Operationen:
sind doch m.E. per Makro schnell durchführbar.
Na dann mach doch mal schnell. Wir warten gespannt auf das
Ergebnis.
Hallo Fritze,
„schnell“ bezog sich auf das Makro, nicht auf die Makrocodeentwicklung, aber warum das Rad neu erfinden, siehe Anhang.
Gruß
Reinhard
' Code von Rene Probst
'
'Variante III - berücksichtigt den Umstand, dass Formatvorlagen mit demselben
'Namen im Quell- und Zieldokument unterschiedlich profiliert sein können
'Schliesslich folgt nun noch eine Lösungsvariante, welche auf den in diesem
'Skript bereits erwähnten Konflikt eingeht, dass Formatvorlagen mit identischem
'Namen in verschiedenen Dateien unterschiedliche Eigenschaften aufweisen können.
'Diese Routine geht davon aus, dass die Zieldatei bereits geöffnet ist.
'Nach dem Starten des Makros mit dem Namen DateienKonkatinieren3 werden Sie als
'erstes aufgefordert, jene Datei auszuwählen, welche an das aktive Dokument
'angehängt werden soll. Die nächsten Schritte geschehen dann im Hintergrund und
'sind zeitintensiv. Der Code analysiert die Dokumente auf Formatvorlagen, welche
'in beiden Dokumenten vorhanden sind und sorgt dafür, dass das Quelldokument
'geklonte Formatvorlagen mit eindeutigem Namen erhält. Dank diesem Aufwand kann
'die individuelle Prägung der Formatvorlagen im Quelldokument transparent in das
'Zieldokument eingebracht werden. Dauerhaft sind diese Veränderungen in der
'Quelldatei allerdings nicht. Nach dem Anhängen der Quelldatei an die Zieldatei
'wird erstere bewusst verworfen und geschlossen und steht dann auf Ihrem
'Datenträger weiterhin im unverändertem Zustand zur Verfügung.
'Das zusammengesetzte Dokument enthält dann z.B. Formatvorlagen mit dem Name
'Standard (aus der Zieldatei) und Standard\* (aus der Quelldatei).
'Kopieren Sie die folgenden Codezeilen in Ihrer VBA-Umgebung in ein leeres Modul
'und üben Sie sich nach dem Aufruf des Makros in etwas Geduld, um das Resultat
'des zeitintensiven Vorganges begutachten zu können.
Option Explicit
'
Private Titel As String
Private Datei As String
Private Q As String
Sub DateienKonkatinieren3()
Dim oDoc As Document, nDoc As Document
Titel = "Dateien konkatinieren"
Q = Chr(34) 'Gänsefüsschen
rc = DokumentAnzahlPruefen 'Feststellen, ob Dok geöffnet
If rc = 0 Then
Set oDoc = ActiveDocument
rc = Einleitung
End If
If rc = 0 Then
rc = QuelldateiOeffnen(oDoc)
If rc = 0 Then Set nDoc = ActiveDocument 'Dok, welches angehängt werden soll
End If
If rc = 0 Then
System.Cursor = wdCursorWait
StatusBar = "Die Formatvorlagen werden nun analysiert."
Application.ScreenUpdating = False
rc = FVAbgleichen(oDoc, nDoc)
End If
If rc = 0 Then
StatusBar = "Die Dokumente werden konkatiniert."
rc = Konkatinieren(oDoc, nDoc)
End If
If Not nDoc Is Nothing Then nDoc.Close SaveChanges:=False
On Error Resume Next
oDoc.Activate 'Zieldokument aktivieren
oDoc.Range(0, 0).Select 'An den Beginn positionieren
On Error GoTo 0
If rc = 0 Then
m = "Die Datei " & Datei & " wurde an die Datei " & oDoc.Name & " angehängt."
StatusBar = m
End If
Application.ScreenUpdating = True
System.Cursor = wdCursorNormal
End Sub
'
Private Function DokumentAnzahlPruefen() As Integer
If Application.Documents.Count = 0 Then 'Kein Zieldokument geöffnet
MsgBox "Öffnen Sie zuerst das Zieldokument.", vbInformation, Titel
DokumentAnzahlPruefen = 8
End If
End Function
Private Function Einleitung() As Integer
m = "Sie werden nun aufgefordert, jenes Dokument auszuwählen, welches an das "
m = m & "aktive Dokument mit dem Namen " 'Hinweis an den/die Benutzer/Benutzerin
m = m & Q & ActiveDocument.FullName & Q & " angehängt werden soll."
If MsgBox(m, vbInformation + vbOKCancel, Titel) = vbCancel Then Einleitung = 4
End Function
Private Function QuelldateiOeffnen(oDoc As Document) As Integer
On Error Resume Next
With Dialogs(wdDialogFileOpen)
Antwort = .Show
Datei = .Name 'Name der ausgewählten Datei
End With
If Err.Number = 5121 Then Err.Clear
Antwort = Antwort - 1
rc = Err.Number
On Error GoTo 0
If rc \> 0 Then
m = "Sie haben mehr als eine Datei ausgewählt oder ein anderer Fehler "
m = m & "ist beim Öffnen der Datei aufgetreten."
MsgBox m, vbExclamation, Titel
QuelldateiOeffnen = 8
Exit Function
End If
If Antwort = 0 Then 'Der Benutzer hat nicht gewählt/abgebrochen
QuelldateiOeffnen = 4
Exit Function
End If
Pfad = Options.DefaultFilePath(wdCurrentFolderPath)
If Not Right(Pfad, 1) = "\" Then Pfad = Pfad & "\" 'Pfadname normalisieren
If Left(Datei, 1) = Chr(34) Then Datei = Mid(Datei, 2, Len(Datei) - 2) 'strip GF
Dateiname = Pfad & Datei
If UCase(Dateiname) = UCase(oDoc.FullName) Then
MsgBox "Quell- und Zieldatei sind identisch.", vbExclamation, Titel
QuelldateiOeffnen = 8
Exit Function
End If
End Function
'
Private Function FVAbgleichen(oDoc As Document, nDoc As Document) As Integer
Dim aDoc As Document, oStyle As Style, oSection As Section
Dim oldS As String, newS As String
For Each oSection In nDoc.Sections 'Dieser Trick ist nötig,....
For i = 1 To 3 '...damit die Formatvorlagen in den Kopf und Fusszeilen...
If Len(oSection.Headers(i).Range.Text) = 1 Then \_
oSection.Headers(i).Range.InsertBefore " "
If Len(oSection.Footers(i).Range.Text) = 1 Then \_
oSection.Headers(i).Range.InsertBefore " "
Next i '...ausgetauscht werden und womit die Abstände vom Blattrand...
Next '...erhalten bleiben.
str1 = Chr(1): str2 = Chr(1): str5 = Chr(1)
For Each oStyle In oDoc.Styles 'Formatvorlagen in der Zieldatei schleifen
str1 = str1 & oStyle.NameLocal & Chr(1)
If oStyle.BuiltIn = True Then
str5 = str5 & oStyle.NameLocal & Chr(1) 'integrierte Formatvorlagen
Else
str2 = str2 & oStyle.NameLocal & Chr(1) 'benutzerdefinierte Formatvorlagen
End If
Next
str3 = Chr(1): str6 = Chr(1)
For Each oStyle In nDoc.Styles 'nun dasselbe, für Datei, welche angehängt wird
str1 = str1 & oStyle.NameLocal & Chr(1)
If oStyle.BuiltIn = True Then
If SearchLoop(nDoc, oStyle.NameLocal) Then
str6 = str6 & oStyle.NameLocal & Chr(1) 'integrierte Formatvorlagen
End If
Else
If SearchLoop(nDoc, oStyle.NameLocal) Then
str3 = str3 & oStyle.NameLocal & Chr(1) 'benutzerdefinierte Formatvorlagen
End If
End If
Next
str4 = Chr(1) 'Abgleich der benutzerdefinierten Formatvorlagen
remstr = Mid(str2, 2)
ofs = InStr(remstr, Chr(1))
While ofs \> 0
oldS = Left(remstr, ofs - 1)
If InStr(str3, Chr(1) & oldS & Chr(1)) \> 0 Then
str4 = str4 & oldS & Chr(1)
End If
remstr = Mid(remstr, ofs + 1)
ofs = InStr(remstr, Chr(1))
Wend
str7 = Chr(1) 'Abgleich der integrierten Formatvorlagen
remstr = Mid(str5, 2)
ofs = InStr(remstr, Chr(1))
While ofs \> 0
oldS = Left(remstr, ofs - 1)
If InStr(str6, Chr(1) & oldS & Chr(1)) \> 0 Then
str7 = str7 & oldS & Chr(1)
End If
remstr = Mid(remstr, ofs + 1)
ofs = InStr(remstr, Chr(1))
Wend
For i = 1 To 2 'Die Formatvorlagen für Kopf- und Fusszeilen...
If i = 1 Then '...müssen zwingend ausgetauscht werden...
tmp = nDoc.Styles(wdStyleHeader).NameLocal
Else '...um die Abstände vom Blattrand zu erhalten.
tmp = nDoc.Styles(wdStyleFooter).NameLocal
End If
If InStr(Chr(1) & str7 & Chr(1), Chr(1) & tmp & Chr(1)) = 0 Then \_
str7 = str7 & tmp & Chr(1) 'wenn noch nicht enthalten
Next i
remstr = Mid(str4, 2) 'Die benutzerdefinierten Formatvorlagen in der...
ofs = InStr(remstr, Chr(1)) '...Datei, welche angehängt werden soll...
While ofs \> 0 '...können schlicht umbenannt werden.
oldS = Left(remstr, ofs - 1)
newS = oldS
flag = 99
While flag \> 0
newS = newS & "\*" 'Formatvorlagenname mit einem \*asterisk\* erweitern
flag = InStr(str1, Chr(1) & newS & Chr(1)) 'prüfen, ob Name nun eindeutig
Wend
RenameStyle nDoc, oldS, newS 'Formatvorlage umbenennen
str1 = str1 & newS & Chr(1) 'neuer Name darf nicht noch einmal vergeben werden
remstr = Mid(remstr, ofs + 1)
ofs = InStr(remstr, Chr(1)) 'nächste FV, welche umbenannt werden muss
Wend
remstr = Mid(str7, 2) 'Die integrierten Formatvorlagen können nicht wirklich...
ofs = InStr(remstr, Chr(1)) '...umbenannt werden
While ofs \> 0
oldS = Left(remstr, ofs - 1)
newS = oldS
flag = 99
While flag \> 0
newS = newS & "\*"
flag = InStr(str1, Chr(1) & newS & Chr(1))
Wend
AddNewStyle nDoc, oldS, newS 'Neue Formatvorlage erstellen
ReplaceLoop nDoc, oldS, newS 'Formatvorlage im Text austauschen
str1 = str1 & newS & Chr(1)
remstr = Mid(remstr, ofs + 1)
ofs = InStr(remstr, Chr(1))
Wend
End Function
'
Private Function Konkatinieren(oDoc As Document, nDoc As Document) As Integer
Dim oRange As Range, s As Integer
s = oDoc.Sections.Count + 1 'nächster Abschnitt im Zieldokument
oDoc.Activate
Set oRange = oDoc.Range.Paragraphs.Last.Range
oRange.SetRange oDoc.Range.End, oDoc.Range.End
oRange.Select 'Abschnittwechsel im Zieldokument einbringen
Selection.InsertBreak Type:=wdSectionBreakNextPage
For i = 1 To 3 'Kopf- und Fusszeilenbereich entkoppeln
oDoc.Sections(s).Headers(i).LinkToPrevious = False
oDoc.Sections(s).Footers(i).LinkToPrevious = False
Next i
oRange.SetRange oDoc.Range.End, oDoc.Range.End 'Formatierter Text aus dem...
oRange.FormattedText = nDoc.Range.FormattedText '...Zieldokument transferieren
For i = 1 To 3
oDoc.Sections(s).Headers(i).Range.FormattedText = \_
nDoc.Sections(1).Headers(i).Range.FormattedText 'Kopfzeileninhalt übertragen
oDoc.Sections(s).Footers(i).Range.FormattedText = \_
nDoc.Sections(1).Footers(i).Range.FormattedText 'Fusszeileninhalt übertragen
If Right(oDoc.Sections(s).Headers(i).Range.Text, 2) = Chr(13) & Chr(13) Then
oDoc.Sections(s).Headers(i).Range.Characters.Last.Delete
End If
If Right(oDoc.Sections(s).Footers(i).Range.Text, 2) = Chr(13) & Chr(13) Then
oDoc.Sections(s).Footers(i).Range.Characters.Last.Delete
End If
Next i
SetLayoutInformation oDoc, nDoc, s 'Seitenlayout übernehmen
End Function
'
Private Sub SetLayoutInformation(oDoc As Document, nDoc As Document, s As Integer)
Dim oPS1 As PageSetup, oPS2 As PageSetup
Set oPS1 = oDoc.Sections(s).PageSetup
Set oPS2 = nDoc.Sections(1).PageSetup
oPS1.Orientation = oPS2.Orientation 'Ausrichtung
oPS1.TopMargin = oPS2.TopMargin 'Abstände
oPS1.BottomMargin = oPS2.BottomMargin
oPS1.LeftMargin = oPS2.LeftMargin
oPS1.RightMargin = oPS2.RightMargin
oPS1.MirrorMargins = oPS2.MirrorMargins 'gegenüberliegende Seiten
oPS1.Gutter = oPS2.Gutter
oPS1.GutterPos = oPS2.GutterPos
oPS1.GutterStyle = oPS2.GutterStyle
oPS1.VerticalAlignment = oPS2.VerticalAlignment 'Seitenausrichtung
oPS1.HeaderDistance = oPS2.HeaderDistance 'Abstände Kopf-/Fusszeile
oPS1.FooterDistance = oPS2.FooterDistance
oPS1.DifferentFirstPageHeaderFooter = oPS2.DifferentFirstPageHeaderFooter
oPS1.OddAndEvenPagesHeaderFooter = oPS2.OddAndEvenPagesHeaderFooter
Dim oPN1 As PageNumbers, oPN2 As PageNumbers 'Seitenzahlenformatierung
Set oPN1 = oDoc.Sections(s).Headers(wdHeaderFooterPrimary).PageNumbers
Set oPN2 = nDoc.Sections(1).Headers(wdHeaderFooterPrimary).PageNumbers
oPN1.NumberStyle = oPN2.NumberStyle
oPN1.HeadingLevelForChapter = oPN2.HeadingLevelForChapter
oPN1.IncludeChapterNumber = oPN2.IncludeChapterNumber
oPN1.ChapterPageSeparator = oPN2.ChapterPageSeparator
oPN1.RestartNumberingAtSection = oPN2.RestartNumberingAtSection
oPN1.StartingNumber = oPN2.StartingNumber
End Sub
'
Private Function SearchLoop(aDoc As Document, tStyle As String) As Boolean
If tStyle = "Absatz-Standardschriftart" Then Exit Function
StatusBar = "Analysiere Formatvorlage " & Q & tStyle & Q & "."
Dim oStory As Range
For Each oStory In aDoc.StoryRanges 'Alle Dokumentbereiche...
Hit = SearchStyle(oStory, tStyle) '...Hauptteil, Kopf- und Fusszeilen...
While (Hit = False) And (Not (oStory.NextStoryRange Is Nothing))
Set oStory = oStory.NextStoryRange '...Textfelder durchsuchen.
Hit = SearchStyle(oStory, tStyle)
Wend
If Hit = True Then Exit For 'sobald ein Treffer eintrifft...
Next '...ist die Sache gegessen
SearchLoop = Hit 'Ergebnis der Suche
End Function
'
Private Function ReplaceLoop(nDoc As Document, s1 As String, s2 As String)
Dim oStory As Range
StatusBar = "Analysiere Formatvorlage " & Q & s1 & Q & "."
For Each oStory In nDoc.StoryRanges 'Formatvorlage in allen Dokumentbereichen...
ReplaceStyle oStory, s1, s2 '...Hauptteil, Kopf- und Fusszeilen, Textfelder...
While Not oStory.NextStoryRange Is Nothing '...etc. ersetzen.
Set oStory = oStory.NextStoryRange
ReplaceStyle oStory, s1, s2 'Bereich, alte Formatvorlage, neue Formatvorlage
Wend
Next
End Function
'
Private Function SearchStyle(oStory As Range, tStyle As String) As Boolean
With oStory.Find 'Suchen einer bestimmten integrierten Formatvorlage...
.ClearFormatting '...in einem bestimmten Dokumententeil.
.Text = ""
.Format = True
.Style = tStyle
SearchStyle = .Execute
End With
DoEvents
End Function
'
Private Function ReplaceStyle(oStory As Range, s1 As String, s2 As String) As Boolean
With oStory.Find 'Austausch einer bestimmten integrierten Formatvorlage...
.ClearFormatting '...in einem bestimmten Dokumententeil.
.Text = ""
.Format = True
.Style = s1
.Replacement.Style = s2
.Execute Replace:=wdReplaceAll
End With
End Function
'
Private Sub RenameStyle(nDoc As Document, s1 As String, s2 As String)
Application.OrganizerRename Source:=nDoc.FullName, Name:=s1, newName:=s2, \_
Object:=wdOrganizerObjectStyles 'Umbenennen einer benutzerdefinierten FV
End Sub
Private Sub AddNewStyle(nDoc As Document, s1 As String, s2 As String)
Dim oStyle As Style, fmt As ParagraphFormat, fnt As Font 'für integrierte FV...
If nDoc.Styles(s1).Type = wdStyleTypeParagraph Then \_
Set fmt = nDoc.Styles(s1).ParagraphFormat '...wird eine neue FV erstellt...
Set fnt = nDoc.Styles(s1).Font '...und analog zum Original profiliert.
Set oStyle = nDoc.Styles.Add(Name:=s2, Type:=nDoc.Styles(s1).Type)
If nDoc.Styles(s1).Type = wdStyleTypeParagraph Then \_
oStyle.ParagraphFormat = fmt 'Absatzformat übertragen
oStyle.Font = fnt 'Zeichenformat übertragen
End Sub
Viel Spaß!
wünscht
Fritze