Ausgewählte Felder kopieren und in xml File abspeichern

Programmierung unter AOO/LO (StarBasic, Python, Java, ...)

Moderator: Moderatoren

cronus
*
Beiträge: 14
Registriert: Di, 04.08.2009 15:03

Re: Ausgewählte Felder kopieren und in xml File abspeichern

Beitrag von cronus »

Hmm hab mir mal angeschaut wie man Java zusammen mit OpenOffice verwenden kann und das kommt mir schon sehr mühsam und kompliziert vor :(
eBayer
******
Beiträge: 556
Registriert: Do, 04.12.2008 14:33
Wohnort: Augsburg

Re: Ausgewählte Felder kopieren und in xml File abspeichern

Beitrag von eBayer »

Hallo, ich habe zwar keine Ahnung von XML..... aber schau doch mal hier herein:
http://www.oooforum.org/forum/viewtopic ... create+xml

Gruß eBayer
Intel(R) Core(TM)2 Quad CPU Q8200 @ 2.33GHz mit 4 GB Memory (3,2 GB aktiv)
Vista Home Premium 32 Bit
openOffice 3.1.1 mit Sun Report Builder 1.1.0 und MySql 5.1
Hauptinteresse ooBase seit 12.2008
cronus
*
Beiträge: 14
Registriert: Di, 04.08.2009 15:03

Re: Ausgewählte Felder kopieren und in xml File abspeichern

Beitrag von cronus »

eBayer hat geschrieben:Hallo, ich habe zwar keine Ahnung von XML..... aber schau doch mal hier herein:
http://www.oooforum.org/forum/viewtopic ... create+xml

Gruß eBayer
jup, hoffentlich antwortet dort einer!
cronus
*
Beiträge: 14
Registriert: Di, 04.08.2009 15:03

Re: Ausgewählte Felder kopieren und in xml File abspeichern

Beitrag von cronus »

ok, da dieses xml schreiben wohl etwas zu schwer ist, möchte ich hier mal die Profis fragen was sie mir allgemein empfehlen würden um das hinzubekommen? Programmiersprache ist egal, muss halt einfach unter OpenOffice sein.
preklov
***
Beiträge: 76
Registriert: Mo, 29.06.2009 09:04
Wohnort: Ruhrgebiet

Re: Ausgewählte Felder kopieren und in xml File abspeichern

Beitrag von preklov »

Hi, Cronus, ich bin zwar beileibe kein Profi, aber da ich sowieso an dem Thema dran bin und nirgends etwas in Starbasic zu finden zu sein scheint, habe ich mal etwas gebastelt.

Du brauchst natürlich zuerst einmal eine Datenquelle. Ich kann mir nur schwer vorstellen, dass Du die aus einer Selektion holen willst, denn der Aufwand ist sicher groß, den Du treiben musst, um auszuschließen, dass die Selektionsdaten nicht kompatibel mit dem benötigten xml-Schema sind. Ich bevorzuge ein Tabellenblatt mit eindeutiger Struktur: 1. Zeile die Feldnamen, jede weitere Zeile ein Datensatz. In diesem calc-Dokument steckt das Makro mit der Datenausgabe in einen DOM-Baum.

Ich habe ein Beispiel erstellt: http://www.uni-due.de/~abi070/files/OOo/xmltest.ods

Darin wird der DOM-Baum erstellt:

Code: Alles auswählen

  oDomBuilder = _
    createUnoService("com.sun.star.xml.dom.DocumentBuilder")
  oDom = oDocBuilder.newDocument()
Alle Teile der xml-Struktur sind Nodes im DOM. Du musst sie erzeugen und in den Baum einfügen, z.B.:

Code: Alles auswählen

oN3 = oDom.createElement("Anschrift")
oder

Code: Alles auswählen

oDom.createTextNode(sCellContent)
Einfügen:

Code: Alles auswählen

oN3.appendChild(oN4)
Und Du brauchst noch Attribute:

Code: Alles auswählen

oN3.setAttribute(Name_des_Attributs, Wert_des_Attributs)
Mehr ist das eigentlich nicht ;-)
Schau Dir die Interfaces auf den API-Seiten an:
http://api.openoffice.org/docs/common/r ... le-ix.html

In der Datei sind auch die benötigten Ausgabeprozeduren. Das ist einmal die Prozedur, die den Output-Stream erzeugt und die Datenausgabe aus dem DOM einleitet:

Code: Alles auswählen

Sub WriteDomToFile(oTree as object, sFilePath as string)

REM Writes the structure of an actual DOM (oTree) line after line
REM   into a simple text file.
REM Mark the line feed (LF). It has to be set explicitly.
REM   Linux: chr(10), Windows: chr(13) + chr(10)

  dim oSimpleFileAccess as object
  dim oOutputStream as object
  dim oTextOutput as object
  dim oTreeNodes as object
  dim i as integer
  
on error goto Catch

  LF = chr(10)
  
REM First set the output stream
  sFilePath = converttourl(sFilePath)
  oSimpleFileAccess = createUnoService("com.sun.star.ucb.SimpleFileAccess")
  with oSimpleFileAccess
    if .exists(sFilePath) then .kill(sFilePath)
    oOutputStream = .openFileWrite(sFilePath)
  end with
  
  oTextOutput = createUnoService("com.sun.star.io.TextOutputStream")
  with oTextOutput
    .OutputStream = oOutputStream
    .setEncoding("UTF-8")
    REM The first line is a processing instruction. It usually isn't part of
    REM   the DOM tree. So we write it separately.
    .WriteString("<?xml version=" + chr(34) + "1.0" + chr(34) + "encoding=" _
      + chr(34) + "UTF-8" + chr(34) + "?>" + LF)
      
    REM A DOM tree can consist of zero, one or more child nodes on the
    REM   root level. They are treated separately.
    if oTree.hasChildNodes() then
      oTreeNodes = oTree.getChildNodes()
      for i = 0 to oTreeNodes.getLength - 1
        PrintDom(oTreeNodes.item(i), oTextOutput, 0, 2)
      next
    end if
    .closeOutput()
  end with
  oOutputStream.closeOutput()

  exit sub
  
Catch:
  print "Fehler " + err + " (" + error(err) + ")"

End Sub
Die eigentliche Ausgabe wird durch PrintDom erzeugt, das rekursiv den Elementbaum durchläuft:

Code: Alles auswählen

Sub PrintDom(oElement as object, oStream as object, _
             iLevel as integer, iIndent as integer)

REM Writes the elements of a DOM tree recursively line after line into a
REM   text file. Mark to start with iLevel 0.
REM Indents lower levels by iIndent characters, except for text nodes: they
REM   are written directly after the element start tag followed by the
REM   element end tag.
REM It is assumed that there are either one text node or one or more other
REM   child nodes to an element, if any.
REM
REM This is a 0.1 version in Starbasic without any validating.
REM Missing: prevent to write parent element tag in case there are child nodes
REM   without any content.
REM Please tell me if there already exists  some other solution.
REM Please feel free to inform me about errors, improvements and amendments.
REM Author: Volker Lenhardt
REM Email: volker.lenhardt@uni.due.de

  dim oElementChildren as object
  dim oChild as object
  dim sLine as string
  dim i as integer
  dim iLen as integer
  dim sNodeName as string
  
  sNodeName = oElement.getNodeName()
  if oElement.getNodeType() = _
      com.sun.star.xml.dom.NodeType.COMMENT_NODE then
    sLine = string(iLevel * iIndent, " ") + "<!-- " _
      + oElement.getNodeValue() + " -->"
    oStream.WriteString(sLine + LF)
  elseif oElement.getNodeType() = _
      com.sun.star.xml.dom.NodeType.PROCESSING_INSTRUCTION_NODE then
    REM Is there a bug? If I create a processing instruction with both
    REM   the target "xml" and data "version..." arguments, the getTarget
    REM   yields "xml", but the getData yields "". The only way is to give
    REM   the whole string as target and "" as data, and to retrieve it as
    REM   nodename. Can someone reproduce this behaviour?
    sLine = string(iLevel * iIndent, " ") + "<?" + sNodeName + "?>"
    oStream.WriteString(sLine + LF)
  else
    sLine = string(iLevel * iIndent, " ") + "<" + sNodeName _
      + AttString(oElement.getAttributes()) + ">"
  
    if oElement.hasChildNodes() then
      oElementChildren = oElement.getChildNodes()
      iLen = oElementChildren.getLength()
      if iLen = 1 then  'Test for text node, assuming that there are no other
                        '  sibling nodes besides.
        oChild = oElementChildren.item(0)
        if oChild.getNodeType() = com.sun.star.xml.dom.NodeType.TEXT_NODE then
          sLine = sLine + oChild.getNodeValue() + _
            "</" + sNodeName + ">"
          oStream.WriteString(sLine + LF)
          exit sub
        end if
      end if
      oStream.WriteString(sLine + LF)
      for i = 0 to iLen - 1
        PrintDom(oElementChildren.item(i), oStream, iLevel + 1, iIndent)
      next
      sLine = string(iLevel * iIndent, " ") + "</" + sNodeName + ">"
      oStream.WriteString(sLine + LF)
    else
      REM If there is no child node, but attributes, the short form is used.
      REM If there are not even attributes, no element tag is written.
      if oElement.hasAttributes() then
        sLine = left(sLine, len(sLine) - 1) + " />"
        oStream.WriteString(sLine + LF)
      end if
    end if
  end if
  
End Sub
In der Beispieldatei sind noch ein paar praktische Hilfsprozeduren.

Vielleicht ist es das, was Du brauchst. Probier es einmal aus.

Schöne Grüße
Volker
Zuletzt geändert von preklov am Di, 11.08.2009 11:10, insgesamt 2-mal geändert.
Schöne Grüße
Volker
Benutzeravatar
komma4
********
Beiträge: 5332
Registriert: Mi, 03.05.2006 23:29
Wohnort: Chon Buri Thailand Asia
Kontaktdaten:

Re: Ausgewählte Felder kopieren und in xml File abspeichern

Beitrag von komma4 »

preklov hat geschrieben:bin zwar beileibe kein Profi
Aber hallo, Volker.
Das sieht schon sehr gut aus!

Kommt auf alle Fälle in meine BASIC-Kruschelkiste und wird von mir getestet.

Vielen Dank!
Cheers
Winfried
aktuell: LO 5.3.5.2 30m0(Build:2) SUSE rpm, unter Linux openSuSE Leap 42.3 x86_64/KDE5
DateTime2 Einfügen von Datum/Zeit/Zeitstempel (als OOo Extension)
preklov
***
Beiträge: 76
Registriert: Mo, 29.06.2009 09:04
Wohnort: Ruhrgebiet

Re: Ausgewählte Felder kopieren und in xml File abspeichern

Beitrag von preklov »

Hi, ich mal wieder.

Der xml-Writer ist nun in der Lage, Nodes zu erkennen, deren Child Nodes und weiteren Nachkommen keine Inhalte haben, und die Ausgabe zu unterdrücken. Dadurch wird der Datenexport aus der Tabelle in den DOM-Baum erheblich vereinfacht.

Er macht das durch Vorschalten einer wiederum rekursiven Suchfunktion:

Code: Alles auswählen

Function HasContent(oElementList as object) as boolean

REM Tests recursively, if there is some child node with content, be it text
REM   or attribute value other than "".
REM It runs in PrintDom before the actual element start tag is written,
REM   so PrintDom can abstain from printing an empty element.

  dim oChildren as object
  dim oChild as object
  dim oAttributes as object
  dim b as boolean
  dim i as integer
  dim j as integer
  dim l as integer
  
  l = oElementList.getLength()
  for i = 0 to l - 1
    oChild = oElementList.item(i)
    if oChild.hasAttributes() then
      oAttributes = oChild.getAttributes()
      for j = 0 to oAttributes.getLength() - 1
        if oAttributes.item(j).getNodeValue() <> "" then
          b = true    
          exit for
        end if
      next
      if b then exit for
    end if
    if oChild.getNodeType() = com.sun.star.xml.dom.NodeType.TEXT_NODE then
      if oChild.getNodeValue() <> "" then
        b = true
        exit for
      end if
    end if
    oChildren = oChild.getChildNodes()
    if oChildren.getLength() = 0 then
      exit for
    else
      b = HasContent(oChildren)
      if b then exit for
    end if
  next
  
  HasContent = b  

End Function
Die Beispieldatei: http://www.uni-due.de/~abi070/files/OOo/xmltest.ods

Bitte testen, auch mit großen Dateien, um zu sehen, ob alles nicht zu langsam ist. Ich habe mit ca. 1300 Datensätzen 13 Sekunden gebraucht.

Schöne Grüße
Volker
Zuletzt geändert von preklov am Di, 11.08.2009 11:11, insgesamt 1-mal geändert.
preklov
***
Beiträge: 76
Registriert: Mo, 29.06.2009 09:04
Wohnort: Ruhrgebiet

Re: Ausgewählte Felder kopieren und in xml File abspeichern

Beitrag von preklov »

Tut mir Leid, aber ich habe einen Fehler entdeckt:

Statt

Code: Alles auswählen

    if oChildren.getLength() = 0 then
      exit for
    else
      b = HasContent(oChildren)
      if b then exit for
    end if
muss es heißen

Code: Alles auswählen

    if oChildren.getLength() <> 0 then
      b = HasContent(oChildren)
      if b then exit for
    end if
Ist in der Beispieldatei korrigiert.

Schöne Grüße
Volker
Schöne Grüße
Volker
cronus
*
Beiträge: 14
Registriert: Di, 04.08.2009 15:03

Re: Ausgewählte Felder kopieren und in xml File abspeichern

Beitrag von cronus »

Vielen Dank Volker. Sieht schon einmal sehr gut aus! Die Beispieldatei kann ich aber leider nicht downloaden, kommt immer der Fehler sie sei nicht vorhanden (Pfad falsch?).

Ansonsten hab ich es inzwischen selber gelöst, bisschen anders als am Anfang gedacht aber es funktioniert ganz gut.
Ich brauch das auslesen der Selektion einfach, hier der Hauptteil meines Codes, für die dies interessiert :P

Code: Alles auswählen

iCount = Freefile
oDoc = ThisComponent
oSels = oDoc.getCurrentSelection() 'Aktuelle Selektion
oData() = oSels.getDataArray()
      sR=1
      sC=1
      for i = lbound(oData) to ubound(oData) 'auslesen der selektierten Zeilen
          oRow() = oData(i)
          for j = lbound(oRow) to ubound(oRow)
              oArray(sR,sC) = oRow(j) 'schreiben des Arrays
	          sC= sC + 1
          next j
      sR = sR + 1
      sC = 1
      next i      
    
      'Überprüfungen zur Selektion
      if oArray(1,1) = Empty then
          msgbox "Bitte keine leeren Zeilen selektieren!"
          stop
      elseif j > 13 then
          msgbox "Bitte nur bis zur Spalte M selektieren!"
          stop
      else
          outputR = 0
          outputC = 0
		  
		  'Schleife zum durchlaufen der Zeilen
	      while outputR < i + 1
	          if oArray(outputR,1) = "Label" then
	          msgbox "Bitte nicht die Überschriftszeile(n) selektieren!"
	          stop
	          end if 
	          
	          if oArray(outputR,4) = Empty then 'Überprüfung ob es ein Titel ist
	              sSQL = chr(13)+"  <!--<field name="+chr(34)+oArray(outputR,1)+chr(34)+"/>-->"
	              goto mark1
	          end if
	          
	          sSQL = chr(13)+"  <field name="+chr(34)+oArray(outputR,1)+chr(34)
	          
	          'Überprüfungen zum Inhalt der Spalten --> hinzufügen von Informationen
	          if oArray(outputR,2) <> Empty then
	              sSQL = sSQL+" modul="+chr(34)+oArray(outputR,2)+chr(34)
	          end if
	                  
	          if oArray(outputR,3) <> Empty then
	              sSQL = sSQL+" name="+chr(34)+oArray(outputR,3)+chr(34)
	          end if

                 '... Weitere Überprüfungen

	          sSQL = sSQL+"/>"
	          
	          mark1:
	          
	          sSQLComplett = sSQLComplett + sSQL 'Zusammenführen der jeweiligen Zeileninhalte
              outputR = outputR + 1    
	      wend
		
      dim args1(0) as new com.sun.star.beans.PropertyValue
	  oDoc.storeasurl(path & filename ,args1()) 'erstellen der Datei
	  open path & filename for Output as iCount 'öffnen der Datei
	  
	  'schreiben des Dateiinhaltes
	  print #iCount, sSQLComplett
	  close #iCount
Sicherlich nicht perfekt, aber er macht das was er sollte.
preklov
***
Beiträge: 76
Registriert: Mo, 29.06.2009 09:04
Wohnort: Ruhrgebiet

Re: Ausgewählte Felder kopieren und in xml File abspeichern

Beitrag von preklov »

Hi Cronus,

Die Datei kannst Du nicht ausführen. Download mit dem Kontextmenü (rechte Maustaste) "Ziel speichern unter...".

Schöne Grüße
Volker
Schöne Grüße
Volker
preklov
***
Beiträge: 76
Registriert: Mo, 29.06.2009 09:04
Wohnort: Ruhrgebiet

Re: Ausgewählte Felder kopieren und in xml File abspeichern

Beitrag von preklov »

Asche über mein Haupt. Ich habe den Verzeichnispfad geändert und vergessen, die Links anzupassen. Ist jetzt geschehen.

Schöne Grüße
Volker
Schöne Grüße
Volker
cronus
*
Beiträge: 14
Registriert: Di, 04.08.2009 15:03

Re: Ausgewählte Felder kopieren und in xml File abspeichern

Beitrag von cronus »

Danke jetzt klappts :)
starenchanter
Beiträge: 2
Registriert: So, 29.08.2010 15:04
Kontaktdaten:

Re: Ausgewählte Felder kopieren und in xml File abspeichern

Beitrag von starenchanter »

Auch wenns schon ein Jahr her ist, könnte man das File wieder hochladen? Cronus oder preklov? ich bräuchte es dringend :)

lg,
starenchanter
.: it's only Rock'n'Roll but i like it!:.
preklov
***
Beiträge: 76
Registriert: Mo, 29.06.2009 09:04
Wohnort: Ruhrgebiet

Re: Ausgewählte Felder kopieren und in xml File abspeichern

Beitrag von preklov »

Hallo starenchanter,

der Link funktioniert wieder. Ich hatte die Datei herausgenommen, da ich dachte, es interessiert sich sowieso keiner dafür.

Du kennst dich sicher mit dem Starten von Makros aus. Das Makro wird gestartet mit "MakeXMLFromSheet". Es greift auf das zur Zeit offene Tabellenblatt zu.

Es ist kein Makro, das du einfach so auf irgendwelche Dateien loslassen kannst. Es muss im Sub MakeXMLFromSheet eingerichtet werden. Der Tabellenname ergibt den Root-Knoten. Die erste Zeile im Tabellenblatt enthält die zu erzeugenden Elementnamen. Falls übergeordnete Elemente erzeugt werden sollen, so ist es vernünftig, die zugehörenden Attribute und Unterelemente in aufeinander folgenden Spalten zu haben.

Das Skript baut einen DOM-Baum auf und gibt ihn wohlgeformt aus. Für die Inhalte ist "MakeXMLFromSheet" zuständig. Es geht im Wesentlichen um die DOM-Befehle
- createElement
- appendChild
- setAttribute.

Ich bin zwar nicht mehr damit beschäftigt, kann aber sicher noch Hilfestellung geben. Englisch ist hoffentlich kein Problem. Sollte aber eine Übersetzung ins Deutsche nötig sein, werde ich sie gerne hinzufügen.

Ich hoffe, es hilft dir.

Schöne Grüße
Volker
starenchanter
Beiträge: 2
Registriert: So, 29.08.2010 15:04
Kontaktdaten:

Re: Ausgewählte Felder kopieren und in xml File abspeichern

Beitrag von starenchanter »

absofuckinglutely fantastic!

Jo ich werd den Code eh etwas umbauen werden/müssen. Hach bin ich froh dass das so schnell ging 8)

so nun ne gute Nacht und sollte ich was brauchen melde ich mich natürlich im fred!

lg,
starenchanter
.: it's only Rock'n'Roll but i like it!:.
Antworten