Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
1184to1188
Aktuelles Verzeichnis
Verzeichnis Index
Übersicht Verzeichnisse
Vorheriger Thread
Rückwärts Blättern
Nächster Thread
Vorwärts blättern
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
Inhaltsverzeichnis

Auslesen von Formatierungen mit .characters

Auslesen von Formatierungen mit .characters
Formatierungen
Hallo,
ich hab hier ein Excel-Sheet vorliegen, bei dem massig Formatierungen innerhalb von Zellen vorgenommen worden sind. Es sind so ca. 1000 Zellen mit Textlängen zwischen 200 und 500 Zeichen, die ich auslesen und in HTML-Code verwandeln möchte, wobei mich nur die Formatierungen
- Fett
- Kursiv
- Schriftfarbe rot (font.colorindex=3)
interesseren.
Soweit ich weiß, kriegt man das nur über die .characters-Eigenschaft raus. Meine bisherige Lösung (nur der Teil, der die Verwandlung vornimmt) sieht folgendermaßen aus:


      
Function fctHTMLFormat2(r As Range, w As IntegerAs String
    
Dim strE As String
    
Dim i As Integer, l As Integer, j As Integer
    
    
If w = vbNo Then
        fctHTMLFormat2 = r.Value
        
Exit Function
    
End If
    
    l = Len(r)
    j = 1
    
If InStr(1, r.Characters(1, 1).Font.FontStyle, "Fett") <> 0 Then
        strE = strE & 
"<b>"
    
End If
    
If InStr(1, r.Characters(1, 1).Font.FontStyle, "Kursiv") <> 0 Then
        strE = strE & 
"<i>"
    
End If
    
If r.Characters(1, 1).Font.ColorIndex = 3 Then
        strE = strE & 
"<span style=" & Chr(34) & "color: rgb(255, 0, 0);" & Chr(34) & ">"
    
End If
    
For i = 2 To l
        
If r.Characters(i, 1).Font.FontStyle <> r.Characters(i - 1, 1).Font.FontStyle Then
            strE = strE & Mid(r, j, i - j)
            j = i
            
If InStr(1, r.Characters(i, 1).Font.FontStyle, "Fett") <> 0 And _
                InStr(1, r.Characters(i - 1, 1).Font.FontStyle, 
"Fett") = 0 Then
                strE = strE & 
"<b>"
            
End If
            
If InStr(1, r.Characters(i, 1).Font.FontStyle, "Fett") = 0 And _
                InStr(1, r.Characters(i - 1, 1).Font.FontStyle, 
"Fett") <> 0 Then
                strE = strE & 
"</b>"
            
End If
            
If InStr(1, r.Characters(i, 1).Font.FontStyle, "Kursiv") <> 0 And _
                InStr(1, r.Characters(i - 1, 1).Font.FontStyle, 
"Kursiv") = 0 Then
                strE = strE & 
"<i>"
            
End If
            
If InStr(1, r.Characters(i, 1).Font.FontStyle, "Kursiv") = 0 And _
                InStr(1, r.Characters(i - 1, 1).Font.FontStyle, 
"Kursiv") <> 0 Then
                strE = strE & 
"</i>"
            
End If
        
End If
        
If r.Characters(i, 1).Font.ColorIndex <> r.Characters(i - 1, 1).Font.ColorIndex Then
            strE = strE & Mid(r, j, i - j)
            j = i
            
If r.Characters(i, 1).Font.ColorIndex = 3 Then
                strE = strE & 
"<span style=" & Chr(34) & "color: rgb(255, 0, 0);" & Chr(34) & ">"
            
Else
                strE = strE & 
"</span>"
            
End If
        
End If
    
Next
    strE = strE & Mid(r, j, i - j)
    
If InStr(1, r.Characters(l, 1).Font.FontStyle, "Fett") <> 0 Then
        strE = strE & 
"</b>"
    
End If
    
If InStr(1, r.Characters(l, 1).Font.FontStyle, "Kursiv") <> 0 Then
        strE = strE & 
"</i>"
    
End If
    
If r.Characters(l, 1).Font.ColorIndex = 3 Then
        strE = strE & 
"</span>"
    
End If
    
    fctHTMLFormat2 = strE
End Function 


Es ist also eine Funktion, die ein Range-Objekt (jeweils eine Zelle) auswertet und das Ergebnis als String (mit HTML-Tags) zurückgibt. Dass aus den einzelnen Strings ein größerer String zusammengesetzt wird (der u.a. HTML-Tabellen enthält) spielt hier nicht zur Sache. Denn das Problem ist ganz eindeutig diese Funktion.
Eigentlich macht die Funktion perfekt das, was ich will - jedoch dauert sie viel zu lange!
Der Parameter w ist dazu da, testweise auf das Auslesen der Formatierungen zu verzichten, bei w=vbNo=7 wird einfach der komlette Zellinhalt als String zurückgegeben, ansonsten erfolgt die detaillierte Format-Auswertung.
OHNE diese Format-Auswertung wird der komplette Code (von allen 1000 Zellen) in ca 2 Sekunden erzeugt, MIT hingegen dauert es je nach "Laune" von Excel zwischen 90 Sekunden und 20 Minuten!!
Hat einer 'ne Ahnung, woran das liegt oder 'ne Idee, wie es eleganter geht?
Im Prinzip ist schnurz, was du in HTML...
13.11.2010 01:26:59
Luc:-?
…machst, Rix,
CSS-Tags oder normale, die zeichenweise Abarbeitung in VBA ist das Entscheidende und daran führt kein Weg vorbei, da du Formatierungen abfragen musst. Es gibt zwar noch ein paar Anhaltspkte, bei deren Beachtung du etwas Zeit sparen könntest, wenn es in 1.Linie darauf ankommt, exakt dasselbe Erscheinungsbild zu erhalten (gemeint sind hier die Effekte, die bei kombinierten Formatierungen auftreten können, von zusätzl BedingtFormaten ganz zu schweigen), aber die Wirken sich spätestens unter XL12 sowieso etwas anders aus. Reguläre Ausdrücke kannst du also vergessen.
Die einzige Methode, das etwas zu beschleunigen, die ich mir vorstellen kann, wäre, die xlinterne HTML-Umwandlung zu benutzen und die dann anschließend zusammenzustreichen. Ggf geht das schneller, wenn du dafür ein Pgm entwickelst…
Ansonsten musst du wohl mit den max 20min leben.
Gruß+schöWE, Luc :-?
Anzeige
AW: Im Prinzip ist schnurz, was du in HTML...
13.11.2010 10:19:04
rlx
Hi Luc,
ja klar, dass die zeichenweise Abarbeitung in VBA das Problem ist, hatte ich schon vermutet. Ich stutze halt trotzdem, weil die Auswertung der .characters-Eigenschaft von Range-Objekten so sehr viel länger dauert, als eine reine String-Auswertung.
(Würde ich z.B. die Zellen ohne Abfrage von .characters in Strings umwandeln und diese dann zeichenweise durchgehen, um - sagen wir mal - alle A mit O zu ersetzen, wäre kaum ein Unterschied zur Schnellvariante spürbar. Bloß leider geht das mit den Formatierungen so nicht - die gehen ja verloren, sobald man die Zelle in einen String verwandelt.)
Das exakt gleiche Erscheinungsbild wie in Excel muss das Ergebnis nicht haben, da es zur Einfügung in Blog-Artikel und -kommentare gedacht ist, die ohnehin nicht alle Formatierungen unterstützen.
Im Original Excel-Sheet sind die Informationen, die ich auslese auf etwa 1200 Zeilen und 30 Spalten verteilt. Um Deinen Vorschlag aufzugreifen, könnte ich diese Informationen erstmal in ein gesondertes Sheet schreiben, wo sie bereits so angeordnet sind, wie sie später als HTML erscheinen sollen.
Wie gehts dann weiter? Wie kann ich per VBA dieses Blatt (bzw. den relevanten Range) "xlintern" in HTML umwandeln und darauf zugreifen?
Anzeige
AW: Im Prinzip ist schnurz, was du in HTML...
13.11.2010 12:07:52
Josef

Hallo ?,
probier doch mal die folgende Funktion.

Function RangetoHTML(rng As Range)
  ' Changed by Ron de Bruin 28-Oct-2006
  ' Working in Office 2000-2010
  Dim fso As Object
  Dim ts As Object
  Dim TempFile As String
  Dim TempWB As Workbook
  
  TempFile = Environ$("temp") & "/" & Format(Now, "dd-mm-yy h-mm-ss") & ".htm"
  
  'Copy the range and create a new workbook to past the data in
  rng.Copy
  Set TempWB = Workbooks.Add(1)
  With TempWB.Sheets(1)
    .Cells(1).PasteSpecial Paste:=8
    .Cells(1).PasteSpecial xlPasteValues, , False, False
    .Cells(1).PasteSpecial xlPasteFormats, , False, False
    .Cells(1).Select
    Application.CutCopyMode = False
    On Error Resume Next
    .DrawingObjects.Visible = True
    .DrawingObjects.Delete
    On Error GoTo 0
  End With
  
  'Publish the sheet to a htm file
  With TempWB.PublishObjects.Add( _
      SourceType:=xlSourceRange, _
      Filename:=TempFile, _
      Sheet:=TempWB.Sheets(1).Name, _
      Source:=TempWB.Sheets(1).UsedRange.Address, _
      HtmlType:=xlHtmlStatic)
    .Publish (True)
  End With
  
  'Read all data from the htm file into RangetoHTML
  Set fso = CreateObject("Scripting.FileSystemObject")
  Set ts = fso.GetFile(TempFile).OpenAsTextStream(1, -2)
  RangetoHTML = ts.ReadAll
  ts.Close
  RangetoHTML = Replace(RangetoHTML, "align=center x:publishsource=", _
    "align=left x:publishsource=")
  
  'Close TempWB
  TempWB.Close savechanges:=False
  
  'Delete the htm file we used in this function
  Kill TempFile
  
  Set ts = Nothing
  Set fso = Nothing
  Set TempWB = Nothing
End Function

Gruß Sepp

Anzeige
AW: Im Prinzip ist schnurz, was du in HTML...
16.11.2010 23:47:58
rlx
Hallo Josef,
Deine Funktion funktioniert zwar, d.h. sie erzeugt jede Menge HTML-Code, aber sie macht leider nicht das was sie soll.
- sie erzeugt einen kompletten HTML-Seitencode (mit head, body usw.) sowie immer auch HTML-Tabellenstrukturen (selbst wenn nur eine Zelle übergeben worden ist), was ich alles nicht brauche.
- hat eine Zelle eine Hintergrundfarbe oder Formatierungen wie Fett, Kursiv und Schriftfarbe wird das in HTML auch korrekt konvertiert, jedoch nur, wenn es die Eigenschaften der GANZEN Zelle sind.
Was sie jedoch NICHT macht (aber darauf kams mir ja eigentlich an!): Sie wertet die Formatierungen INNERHALB von Zellen (d.h. die .characters-Eigenschaft nicht aus). Abweichende Formatierungen innerhalb von Zellen werden einfach ignoriert!
Damit ist die Funktion für mich leider nicht zu gebrauchen.
Anzeige
AW: Im Prinzip ist schnurz, was du in HTML...
18.11.2010 00:56:11
fcs
Hallo rlx,
wenn du das Kopieren der Daten in die temporäre Arbeitsmappe anpasst, dann wird auch der HTML-Code für das Format einzelner Zeichen generiert.
Gruß
Franz
Function RangetoHTML(rng As Range)
' Changed by Ron de Bruin 28-Oct-2006
' Working in Office 2000-2010
Dim fso As Object
Dim ts As Object
Dim TempFile As String
Dim TempWB As Workbook
TempFile = Environ$("temp") & "/" & Format(Now, "dd-mm-yy h-mm-ss") & ".htm"
'Copy the range and create a new workbook to past the data in
Set TempWB = Workbooks.Add(1)
With TempWB.Sheets(1)
rng.EntireColumn.Copy
'Spaltenbreiten kopieren
.Cells(1, 1).PasteSpecial Paste:=xlPasteFormats
.UsedRange.ClearFormats
'Zellbereich kopieren
rng.Copy .Cells(1, 1)
Application.CutCopyMode = False
On Error Resume Next
.DrawingObjects.Visible = True
.DrawingObjects.Delete
On Error GoTo 0
End With
'Publish the sheet to a htm file
With TempWB.PublishObjects.Add( _
SourceType:=xlSourceRange, _
Filename:=TempFile, _
Sheet:=TempWB.Sheets(1).Name, _
Source:=TempWB.Sheets(1).UsedRange.Address, _
HtmlType:=xlHtmlStatic)
.Publish (True)
End With
'Read all data from the htm file into RangetoHTML
Set fso = CreateObject("Scripting.FileSystemObject")
Set ts = fso.GetFile(TempFile).OpenAsTextStream(1, -2)
RangetoHTML = ts.ReadAll
ts.Close
RangetoHTML = Replace(RangetoHTML, "align=center x:publishsource=", _
"align=left x:publishsource=")
'Close TempWB
TempWB.Close savechanges:=False
'Delete the htm file we used in this function
Kill TempFile
Set ts = Nothing
Set fso = Nothing
Set TempWB = Nothing
End Function

Anzeige
AW: Auslesen von Formatierungen mit .characters
13.11.2010 08:28:02
Formatierungen
Hallo rlx,
die nachfolgende Variante ist deutlich schneller. Die Formatinformationen der einzelnen Zeichen werden in Arrays geladen. Das reduziert die Gesamtzahl der erforderlichen Berechnungen.
Die Laufzeit ist auf meinem Rechner im günstigsten Fall 1:23 (deine Version 2:45) für 1000 Zeilen, variierte aber erstaunlich stark (Warum?). Im Extremfall betrug auf meiner Kiste die Rechenzeit 0,5 bis 1 Sekunde pro Zelle.
Gruß
Franz
Function fctHTMLFormat2(r As Range, w As Integer) As String
Dim strE As String, sText As String
Dim i As Integer, l As Integer, j As Integer
Dim arrStyle() As String, arrFett() As Boolean, arrItalic() As Boolean, _
arrColorIndex3() As Boolean
sText = r.Value
If w = vbNo Then
fctHTMLFormat2 = sText
Exit Function
End If
l = Len(sText)
ReDim arrStyle(1 To l), arrFett(1 To l), arrItalic(1 To l), arrColorIndex3(1 To l)
For i = 1 To l
arrStyle(i) = r.Characters(i, 1).Font.FontStyle
arrFett(i) = InStr(1, arrStyle(i), "Fett")  0
arrItalic(i) = InStr(1, arrStyle(i), "Kursiv")  0
arrColorIndex3(i) = r.Characters(i, 1).Font.ColorIndex = 3
Next
j = 1
If arrFett(1) Then
strE = strE & ""
End If
If arrItalic(1) Then
strE = strE & ""
End If
If arrColorIndex3(1) Then
strE = strE & ""
End If
For i = 2 To l
If arrStyle(i)  arrStyle(i - 1) Then
strE = strE & Mid(sText, j, i - j)
j = i
If arrFett(i) And Not arrFett(i - 1) Then
strE = strE & ""
End If
If Not arrFett(i) And arrFett(i - 1) Then
strE = strE & ""
End If
If arrItalic(i) And Not arrItalic(i - 1) Then
strE = strE & ""
End If
If Not arrItalic(i) And arrItalic(i - 1) Then
strE = strE & ""
End If
End If
If arrColorIndex3(i)  arrColorIndex3(i - 1) Then
strE = strE & Mid(sText, j, i - j)
j = i
If arrColorIndex3(i) Then
strE = strE & " _
Else
strE = strE & ""
End If
End If
Next
strE = strE & Mid(sText, j, i - j)
If arrFett(l) Then
strE = strE & ""
End If
If arrItalic(l) Then
strE = strE & ""
End If
If arrColorIndex3(l) Then
strE = strE & ""
End If
fctHTMLFormat2 = strE
End Function

Anzeige
AW: Auslesen von Formatierungen mit .characters
13.11.2010 10:04:45
Formatierungen
Hallo Franz,
vielen Dank für Deine Mühen. Ich habe Deine Variante mal eben getestet. Nachdem ich die strE-Zuweisungen wieder korrekt gesetzt hatte ist der Ergebnisstring der gleiche wie mit meinem Originalcode.
Der erste Durchlauf dauerte ca. 9 Minuten, das ist deutlich besser als mein bisher schlechtestes Ergebnis, aber trotzdem schlechter als mein bisher bestes.
Tests mit weniger Zellen ergaben, dass die Array-Variante wohl tatsächlich immer etwa genau doppelt so schnell ist.
Das ist zwar ein Fortschritt, aber natürlich nicht in dem Maße, wie ich mir das erhoffte.
Ich werde es dann so oder so ähnlich bei mir einbauen, es sei denn, Dir oder anderen fällt noch was besseres ein.
thx
rlx
Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige