markierten Tabelleninhalt exportieren

  • Word

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von roddy.

    markierten Tabelleninhalt exportieren

    Hallo,

    ich möchte aus einer Doc-Datei bestimmte markierte Zellen aus einer Tabelle in eine txt-datei exportieren. Danach soll der Text auch noch umformatiert/sortiert werden. Ungefähr so:

    Tabelle in Word (in etwa):

    | Kopf A | Kopf B | Kopf C | Kopf D |
    | Text A | Text B | Text C | Text D |


    Ergebnis in der Textdatei:

    Kopf A
    Text A

    Kopf B
    Text B

    Kopf C
    Text C

    Kopf D
    Text D



    Ich hab schon viel experimentiert aber da ich total neu bei VBA bin ist da nichts vernünftiges bei rausgekommen.
    Könnt ihr mir ein paar Hilfreiche Tips geben, wie man so etwas realisieren kann. Ich wäre euch sehr dankbar.

    soegel
    Was das Arbeiten mit Text-Dateien angeht, empfehle ich dir, in der VB-Hilfe den Eintrag "TextStream-Objekt" und dessen Eigenschaften und Methoden anzusehen. In deinem Beispiel würde sich da die "WriteLine"-Methode anbieten, denke ich.

    Was das Auslesen der Daten in der Tabelle angeht, kannst du dir mal den Hilfe-Eintrag "Table-Objekt" ansehen.

    Hier noch ein Code-Schnipsel, der dir als Inspiration dienen soll:

    Visual Basic-Quellcode

    1. For i = 1 To Selection.Cells.Count
    2. MsgBox Selection.Cells(i)
    3. MsgBox Selection.Cells(i).Column.Index
    4. MsgBox Selection.Cells(i).Row.Index
    5. Next
    Hallo, ich bin jetzt soweit:

    Visual Basic-Quellcode

    1. Sub test()
    2. Dim i As Integer
    3. Dim FileName As String
    4. Dim arrOrdner As Variant
    5. Dim iOrdner As Integer
    6. Dim sDrive As String
    7. Dim sOrdner As String
    8. Dim sTmp As String
    9. Dim FullFilePath As String
    10. Dim ueberschreiben As String
    11. Dim position As Long
    12. sOrdner = InputBox("Wo soll die Datei gespeichert werden. Pfad mit Laufwerksbuchstaben angeben. (zb: C:\Ordner1\Ordner2) (nicht vorhandene Verzeichnisse werden erstellt):")
    13. FileName = InputBox("Namen der Export-Datei angeben. Dateiendung '.ts' wird automatisch angehängt.")
    14. If sOrdner = "" Then Exit Sub
    15. If FileName = "" Then Exit Sub
    16. 'Eventuelles "\" am Ende des eingegebenen Pfades entfernen
    17. If Right(sOrdner, 1) = "\" Then
    18. sOrdner = Left(sOrdner, Len(sOrdner) - 1)
    19. End If
    20. neuername:
    21. 'Check auf Existenz der Datei
    22. FullFilePath = sOrdner & "\" & FileName & ".ts"
    23. If CheckPath(FullFilePath) Then
    24. nochmalfragen:
    25. ueberschreiben = InputBox("Die Datei existiert bereits." & Chr(13) & _
    26. "Überschreiben? j/n")
    27. If ueberschreiben = "n" Then
    28. FileName = InputBox("Anderen Dateinamen angeben. Dateiendung '.ts' wird automatisch angehängt.")
    29. GoTo neuername
    30. ElseIf ueberschreiben = "j" Then
    31. GoTo weitermachen
    32. Else: GoTo nochmalfragen 'falls ungültige Eingabe
    33. End If
    34. Else
    35. weitermachen:
    36. arrOrdner = fncFolders(sOrdner)
    37. For iOrdner = UBound(arrOrdner) To 1 Step -1
    38. If fncIfFolderExists(CStr(arrOrdner(iOrdner))) Then
    39. iOrdner = iOrdner - 1
    40. Else
    41. MkDir arrOrdner(iOrdner)
    42. End If
    43. Next iOrdner
    44. Set fs = CreateObject("Scripting.FileSystemObject")
    45. Set a = fs.CreateTextFile(sOrdner & "\" & FileName & ".ts", True)
    46. 'If Selection.Tables(1).Rows.Count > 1 Then
    47. 'MsgBox ("Bitte nur eine Tabellenzeile markieren!")
    48. 'Exit Sub
    49. 'End If
    50. For i = 1 To Selection.Cells.Count
    51. ' Hier werden die "Überschriften" zugeordnet und Kommentar-Symbole vorgesetzt.
    52. ' Vorraussetzung ist, das die Zelleninhalte ohne Zeilenumbruch eingefügt werden.
    53. If i = 1 Then
    54. a.write ("# - Nummer: ")
    55. ElseIf i = 2 Then
    56. a.write ("# - Stichwort: ")
    57. ElseIf i = 3 Then
    58. a.write ("# - Beschreibung: ")
    59. ElseIf i = 4 Then
    60. a.write ("# - Erwartung: ")
    61. Else
    62. a.write ("# ")
    63. End If
    64. 'Einfügen der Zelleninhalte
    65. a.WriteLine (Left(Selection.Cells(i), 500))
    66. 'position = 500
    67. 'Do While Right(Selection.Cells(i), position) <> ""
    68. 'a.WriteLine (Mid(Selection.Cells(i), position, position + 500))
    69. 'position = position + 500
    70. 'Loop
    71. ' Das Zeichen durch ein Leerzeichen ersetzen
    72. 'With Selection.Find
    73. '.Text = ""
    74. '.ClearFormatting
    75. '.Replacement.Text = " "
    76. '.Replacement.ClearFormatting
    77. '.Execute Replace:=wdReplaceOne, Forward:=True
    78. 'End With
    79. Next
    80. a.Close
    81. End If
    82. End Sub
    83. '#####FUNKTIONEN#######
    84. Private Function fncFolders(sfolder As String) As Variant
    85. Dim arr() As String
    86. Dim iCounter As Integer, ifolder As Integer
    87. ReDim arr(1 To 1)
    88. arr(1) = sfolder
    89. ifolder = 1
    90. For iCounter = Len(sfolder) To 4 Step -1
    91. If Mid(sfolder, iCounter, 1) = "\" Or iCounter = 1 Then
    92. ifolder = ifolder + 1
    93. ReDim Preserve arr(1 To ifolder)
    94. arr(ifolder) = Left(sfolder, iCounter - 1)
    95. End If
    96. Next iCounter
    97. fncFolders = arr
    98. End Function
    99. Private Function fncIfFolderExists(sfolder As String) As Boolean
    100. Dim sOld As String
    101. sOld = CurDir
    102. On Error Resume Next
    103. ChDrive Left(sfolder, 1)
    104. ChDir sfolder
    105. If Err = 0 Then fncIfFolderExists = True
    106. On Error GoTo 0
    107. ChDrive Left(sOld, 1)
    108. ChDir sOld
    109. End Function
    110. Private Function CheckPath(strPath As String) As Boolean
    111. If Dir$(strPath) <> "" Then
    112. CheckPath = True
    113. Else
    114. CheckPath = False
    115. End If
    116. End Function


    ich hoffe das schockiert hier niemanden, wenn ich hier soviel Code poste :whistling:

    Also ich habe da ein paar Probleme:

    Zeile 52)
    Hier soll überprüft werden wieviele ZEILEN aus der Tabelle selektiert wurden. Denn bei mehr als einer selektierten Zeile Funktioniert das makro nicht. (die 'eine' Zeile die erlaubt ist darf aber beliebig viele Spalten haben.)

    Leider funktioniert dieser Check nicht richtig. Stimmt da was mit den Objekten 'Selection.Tables(1).Rows.Count' nicht?

    Zeile 74 bis 80 )
    Nach 500 Zeichen soll ein Zeilenumbruch eingefügt werden. Das was da steht ist wohl eher ein verzweifelter Versuch von mir (der auch nicht funktioniert) Wie würdet ihr es machen?

    Zeile 83 bis 90)
    Aus irgendeinem Grund wird an einigen Stellen in der Textdatei auch dieses Quadrat-Teichen mit eingefügt (kann hier im Forum offensichtlich nicht angezeigt werden) Ich weiss nicht woran das liegt. Wie kann ich das verhindern?
    Ich habe versucht es mit einem Zeichenaustausch zu managen, aber das funktionierte leider nicht. Ich vermute mal deswegen, weil das Quadrat-Symbol erst beim Einfügen entsteht, und vorher ja nicht in der Word datei existiert.


    noch eine andere Frage: Wie kann ich das Ereignis abfangen, wenn der Benutzer bei einer InputBox auf die Abbrechen-Schaltfläche oder oben auf das 'X' des Dialoges klickt?

    Ich hoffe jmd. kann mir helfen, und ich habe mich verständlich ausgedrückt.


    MfG

    soegel

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „soegel“ ()

    zu Zeile 52)

    Lass Tables(1) weg. So wie du es jetzt hast, werden die Zeilen der gesamten Tabelle, innerhalb der sich die Markierung befindet, gezählt, also statt Zeile 52:

    Visual Basic-Quellcode

    1. If Selection.Rows.Count > 1 Then


    zu Zeile 74 bis 80)

    Ich denke, so müsste es funktionieren:

    Visual Basic-Quellcode

    1. For k = 1 To Len(Selection.Cells(i)) Step 500
    2. a.WriteLine Mid(Selection.Cells(i), k, 500)
    3. Next


    zu Zeile 83 bis 90)

    Am Ende jeder Zelle einer Word-Tabelle sind die Zeichen mit den ASCII-Werten 13 und 7. Das mit der 7 ist für das Quadrat verantwortlich.

    Ich nehme an, dass diese Zeichen im Range-String des Word-Dokuments enthalten sind, um Tabellenzellen kennzuzeichnen.

    Am besten weist du in Zeile 73 den Zellinhalt einer Variablen zu, wobei du die erwähnten 2 Zeichen abschneidest:

    Visual Basic-Quellcode

    1. Zellinhalt = Left(Selection.Cells(i), Len(Selection.Cells(i)) - 2)


    Und danach verwendest du überall statt "Selection.Cells(i)" diese Variable (auch in meinem Beispiel für die Zeilen 74 bis 80)


    Zu der X-Schaltfläche:

    Wenn man bei einer InputBox auf Abbrechen oder das X klickt, wird ein Leerstring ("") zurückgegeben.


    Noch ein paar Tipps:

    Versuche "GoTo" und "On Error ..." soweit es geht zu vermeiden. Es gibt seltene Fälle, bei denen ich es auch noch verwende, aber das sollte die Ausnahme ein.

    Wenn man GoTo benutzt, verliert der Code an Übersichtlichkeit.
    Ich würde statt der Zeilen 23 bis 39 folgendes machen:
    (Ich war so frei und hab aus der InputBox eine MsgBox gemacht.)

    Visual Basic-Quellcode

    1. Do
    2. FullFilePath = sOrdner & "\" & FileName & ".ts"
    3. If Dir(FullFilePath) = "" Then
    4. Exit Do
    5. Else
    6. If MsgBox("Die Datei existiert bereits." & Chr(13) & _
    7. "Überschreiben?", vbYesNo) = vbYes Then
    8. Exit Do
    9. Else
    10. FileName = InputBox("Anderen Dateinamen angeben. Dateiendung '.ts' wird automatisch angehängt.")
    11. End If
    12. End If
    13. Loop


    Und in Zeile 95 noch das "End If" entfernen.

    Wie du in meinem Beispiel siehst, ist es auch nicht viel aufwändiger ohne die Funktion "CheckPath".

    zu deiner FolderExists-Funktion:

    Das FileSystemObject-Objekt hat eine FolderExists-Methode (näheres in der VB-Hilfe). Das geht dann etwas einfacher als deine Funktion. Außerdem stört mich bei dir dieses "On Error ...".



    Ich hoffe, ich konnte dir damit weiterhelfen.
    Hallo,
    ich habe alles umgesetzt.
    Auch die FolderExists-Methode vom SystemObject-Object ist schon drin.
    Das ganze sieht jetzt so aus.

    Visual Basic-Quellcode

    1. Sub test()
    2. Dim i As Integer
    3. Dim FileName As String
    4. Dim arrOrdner As Variant
    5. Dim iOrdner As Integer
    6. Dim sDrive As String
    7. Dim sOrdner As String
    8. Dim sTmp As String
    9. Dim FullFilePath As String
    10. Dim Zelleninhalt As String
    11. Dim SpaceLen As Single
    12. If Selection.Rows.Count > 1 Then
    13. MsgBox ("Bitte nur eine Tabellenzeile markieren!")
    14. Exit Sub
    15. End If
    16. sOrdner = InputBox("Wo soll die Datei gespeichert werden. Pfad mit Laufwerksbuchstaben angeben. (zb: C:\Ordner1\Ordner2) (nicht vorhandene Verzeichnisse werden erstellt):")
    17. FileName = InputBox("Namen der Export-Datei angeben. Dateiendung '.ts' wird automatisch angehängt.")
    18. If sOrdner = "" Then Exit Sub
    19. If FileName = "" Then Exit Sub
    20. 'Eventuelles "\" am Ende des eingegebenen Pfades entfernen
    21. If Right(sOrdner, 1) = "\" Then
    22. sOrdner = Left(sOrdner, Len(sOrdner) - 1)
    23. End If
    24. 'Checkt die Existens der Datei
    25. Do
    26. FullFilePath = sOrdner & "\" & FileName & ".ts"
    27. If Dir(FullFilePath) = "" Then
    28. Exit Do
    29. Else
    30. If MsgBox("Die Datei existiert bereits." & Chr(13) & _
    31. "Überschreiben?", vbYesNo) = vbYes Then
    32. Exit Do
    33. Else
    34. Do
    35. FileName = InputBox("Anderen Dateinamen angeben. Dateiendung '.ts' wird automatisch angehängt.")
    36. If FileName = "" Then 'Export wird für Schaltfl. 'Abbrechen' und bei leerem Namen abbgebrochen
    37. MsgBox ("Exportierung abbgebrochen.")
    38. Exit Sub
    39. Else
    40. Exit Do
    41. End If
    42. Loop
    43. End If
    44. End If
    45. Loop
    46. Set fs = CreateObject("Scripting.FileSystemObject")
    47. arrOrdner = fncFolders(sOrdner)
    48. For iOrdner = UBound(arrOrdner) To 1 Step -1
    49. If fs.FolderExists(CStr(arrOrdner(iOrdner))) Then
    50. 'TeilOrdner überspringen, falls schon vorhanden
    51. iOrdner = iOrdner - 1
    52. Else
    53. 'andernsfalls TeilOrdner erstellen
    54. MkDir arrOrdner(iOrdner)
    55. End If
    56. Next iOrdner
    57. Set a = fs.CreateTextFile(sOrdner & "\" & FileName & ".ts", True)
    58. For i = 1 To Selection.Cells.Count
    59. ' Hier werden die "Überschriften" zugeordnet und Kommentar-Symbole vorgesetzt.
    60. ' Vorraussetzung ist, das die Zelleninhalte ohne Zeilenumbruch eingefügt werden.
    61. If i = 1 Then
    62. a.write ("# - Nummer: ")
    63. SpaceLen = 8
    64. ElseIf i = 2 Then
    65. a.writeline ("#")
    66. a.write ("# - Stichwort: ")
    67. SpaceLen = 11
    68. ElseIf i = 3 Then
    69. a.writeline ("#")
    70. a.write ("# - Beschreibung: ")
    71. SpaceLen = 14
    72. ElseIf i = 4 Then
    73. a.writeline ("#")
    74. a.write ("# - Erwartung: ")
    75. SpaceLen = 11
    76. Else
    77. a.writeline ("# ")
    78. SpaceLen = 2
    79. End If
    80. 'Inhalt der Aktuellen Zelle in Variable schreiben
    81. Zelleninhalt = Left((Selection.Cells(i)), Len((Selection.Cells(i))) - 2)
    82. 'Einfügen der Zelleninhalte
    83. For k = 1 To Len(Zelleninhalt) Step 500
    84. If k > 1 Then a.write ("# - " & Space(SpaceLen))
    85. a.writeline Mid(Zelleninhalt, k, 500)
    86. Next
    87. Next
    88. a.Close
    89. 'MsgBox Selection.Cells(i).Column.Index
    90. 'MsgBox Selection.Cells(i).Row.Index
    91. End Sub
    92. Private Function fncFolders(sfolder As String) As Variant
    93. Dim arr() As String
    94. Dim iCounter As Integer, ifolder As Integer
    95. ReDim arr(1 To 1)
    96. arr(1) = sfolder
    97. ifolder = 1
    98. For iCounter = Len(sfolder) To 4 Step -1
    99. If Mid(sfolder, iCounter, 1) = "\" Or iCounter = 1 Then
    100. ifolder = ifolder + 1
    101. ReDim Preserve arr(1 To ifolder)
    102. arr(ifolder) = Left(sfolder, iCounter - 1)
    103. End If
    104. Next iCounter
    105. fncFolders = arr
    106. End Function



    Ich habe das Programm jetzt mal umfangreichen Tests unterzogen, was das erstellen von Ordnern und den eigentlichen Export-Dateien betrifft. Dabei habe ich unterschiedliche Kombinationen ausprobiert.
    Beispielsweise:
    erst Export nach Z:\hallo\datei.ts
    danach nach Z:\hallo\Ordner2\datei.ts

    oder:
    erst Export nach Z:\hallo\hallo2\Ordner\datei.ts
    und dann: Z:\hallo\datei.ts

    Gelegentlich (bei bestimmten Kombinationen der vorhandenen und noch zu erstellenden Ordner) bekomme ich nun einen Laufzeitfehler 76 "Pfad nicht gefunden". Der Debugger zeigt auf "Set a = fs.CreateTextFile(sOrdner & "\" & FileName & ".ts", True)" (Zeile 65).

    Ich denke mal das mit Pfad nicht gefunden, "sOrdner" in dem Ausdruck gemeint ist.
    Das würde ja heissen, dass das was in den Zeilen 52 bis 63 steht, irgendwie nicht so ganz hinhaut. Also die Überprüfung/Erstellung des Ordnerbaumes.
    Mal funktionierts, mal nicht.
    Kann der Fachmann da irgendwas fadenscheiniges erkennen? Vllt ist meine Vermutung auch falsch und der Fehler liegt woanders.

    edit: tatsächlich scheint hier jemad ziehmlich das gleiche Problem zu haben: tek-tips.com/viewthread.cfm?qid=1161048&page=1.
    Die vorgeschlagene "Brute-Force"-Prozedur, ist die wirklich nötig? Ich hoffe noch, ich kann das problem schneller lösen und das es nur eine kleine sache ist :)

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „soegel“ ()

    In Zeile 58 machst du das:

    Visual Basic-Quellcode

    1. iOrdner = iOrdner - 1


    Das ist aber genau das, was "Next iOrdner" bei "Step -1" auch macht. Vielleicht liegt da der Hund begraben.

    Vielleicht hilft dir eine andere Herangehensweise:


    Visual Basic-Quellcode

    1. Private Function fncFolders(sfolder As String) As String()
    2. Dim arr() As String
    3. Dim iCounter As Integer, ifolder As Integer
    4. arr = Split(sfolder, "\")
    5. For iCounter = 1 To Ubound(arr)
    6. arr(iCounter) = arr(iCounter - 1) & "\" & arr(iCounter)
    7. Next
    8. fncFolders = arr
    9. End Function


    Die Split-Funktion erzeugt ein String-Array, das einen String am Trennzeichen trennt (mehr Infos in der VB-Hilfe).

    Wenn in obiger Funktion sfolder = "C:\Ordner1\Ordner2\Ordner3" ist, bekommt arr durch Split folgende Werte: arr(0)="C:", arr(1)="Ordner1", arr(2)="Ordner2", arr(3)="Ordner3".



    statt Zeile 54 bis 63:

    Visual Basic-Quellcode

    1. arrOrdner = fncFolders(sOrdner)
    2. For iOrdner = 1 To UBound(arrOrdner)
    3. If Not fs.FolderExists(arrOrdner(iOrdner)) Then
    4. MkDir arrOrdner(iOrdner)
    5. End If
    6. Next iOrdner



    Hab grad erst deinen Edit gesehen. Mein Code zielt im Prinzip auf das gleiche ab, wie die Lösung in deinem Link, das im Link ist nur noch etwas kürzer.

    Dann bräuchtest du nämlich statt der Zeilen 54 bis 63 nur das hier:

    Visual Basic-Quellcode

    1. myMkDir sOrdner

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „roddy“ ()