Seite 1 von 1

CALC: BASE-Abfrage in Tabelle bekommen

Verfasst: Mo, 26.03.2012 08:26
von crush
Moin, ich habe mir mit OpenOffice eine Datenbank mit Base angelegt. Auf diese kann ich nun in Calc zugreifen über "Datenquellen". Da kann man ja einfach eine gespeicherte Abfrage per drag&drop in eine Tabelle ziehen. Ich würde das gern mit einem Makro erreichen, aber mit "Makro aufzeichnen" scheint das nicht zu funktionieren. Wie müsste der Code aussehen, um eine Abfrage um die Tabelle zu bekommen?

Danke für eure Anregungen
crush




Moderation,4: verschoben in BASIC-Unterbereich, wo alle Makro-Fragen hin gehören; Betreff angepasst

Re: CALC: BASE-Abfrage in Tabelle bekommen

Verfasst: Mo, 26.03.2012 08:47
von komma4
Willkommen im Forum.

Benutze die SUCHE (ggfs. über Google mit site:http://de.openoffice.info/) und finde viele Hinweise auf Deine Frage, wenn Du nach Resultset suchst.


Viel Erfolg!

Re: CALC: BASE-Abfrage in Tabelle bekommen

Verfasst: Mo, 26.03.2012 12:07
von crush
Hallo, ich habe nun schon etwas zustande gebracht.

Code: Alles auswählen

REM  *****  BASIC  *****


sub Main
rem ----------------------------------------------------------------------
rem define variables
Dim DatabaseContext As Object
Dim DataSource As Object
Dim Connection As Object
Dim InteractionHandler as Object
Dim Statement As Object
Dim ResultSet As Object
dim document   as object
dim dispatcher as object
dim args2(0) as new com.sun.star.beans.PropertyValue
dim args3(0) as new com.sun.star.beans.PropertyValue

rem ----------------------------------------------------------------------
rem get access to the document
document   = ThisComponent.CurrentController.Frame
dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
 
DatabaseContext = createUnoService("com.sun.star.sdb.DatabaseContext")
DataSource = DatabaseContext.getByName("Neue Datenbank3")
 
rem If Not DataSource.IsPasswordRequired Then
  Connection = DataSource.GetConnection("user","pw")
rem Else
rem  InteractionHandler = createUnoService("com.sun.star.sdb.InteractionHandler")
rem  Connection = DataSource.ConnectWithCompletion(InteractionHandler)
rem End If
 
Statement = Connection.createStatement()
ResultSet = Statement.executeQuery("SELECT ""ksttr"", ""bezeichnung_0_"" FROM ""heinebekost"" WHERE ""ksttr"" BETWEEN 1301 AND 1370") rem ""ksttr"", ""bezeichnung_0_""

rem ----------------------------------------------------------------------
dim args1(0) as new com.sun.star.beans.PropertyValue
args1(0).Name = "ToPoint"
args1(0).Value = "$D$2"

dispatcher.executeDispatch(document, ".uno:GoToCell", "", 0, args1())

rem ----------------------------------------------------------------------
args2(0).Name = "StringName"
args3(0).Name = "StringName"

If Not IsNull(ResultSet) Then
  While ResultSet.next
    args2(0).Value = ResultSet.getString(1)
    args3(0).Value = ResultSet.getString(2)
    dispatcher.executeDispatch(document, ".uno:EnterString", "", 0, args2())
    rem HIER MÜSSTE EIN CODE STEHEN, DER DEN CURSER NACH RECHTS STELLT
    dispatcher.executeDispatch(document, ".uno:EnterString", "", 0, args3())
    dispatcher.executeDispatch(document, ".uno:JumpToNextCell", "", 0, Array())
  Wend
End If



end sub
Meine Frage: Das Resultset ist zweispaltig. Diese beiden Spalten werden dann über die Schleife ganz unten ausgegeben. Ich finde aber keinen Code wie erst eine Zelle nach rechts gesprungen wird bevor args3 ausgegeben wird und dann "JumpToNextCell" ausgefüht wird. Also habe ich bis jetzt immer nur eine Spalte, und die zweite fehlt. Wie komme ich nach dem schreiben von args2 in die Zelle rechts daneben? Wenn ich von Hand eine Tabelle fülle, springt der Cursor nach mehrmaligem betätigen von "tab" und anschließendem "Return" wieder in die erste Spalte der nächsten Zeile. Klappt das mit BASIC auch?

Gruß crush

Re: CALC: BASE-Abfrage in Tabelle bekommen

Verfasst: Di, 27.03.2012 07:52
von crush
Niemand eine Ahnung, oder muss ich das Resultset zweimal durchlaufen, und beide Spalten getrennt voneinander ausgeben lassen?

Gruß crush

Re: CALC: BASE-Abfrage in Tabelle bekommen

Verfasst: Di, 27.03.2012 08:35
von komma4
Wenn Du Dich mal ein wenig umgesehen hättest, dann wäre Dir aufgefallen, dass fast niemand (der Makros schreibt!) dispatcher Code verwendet.

Zum Setzen kannst Du einfachst .getCellByPosition nehmen.

Für grössere Datenmengen empfiehlt sich das Setzen aller Daten auf einmal: .setDataArray( aDaten )


Ein Beispiel in einer Anwendung, siehe meine Extension OOoDIL - DokumentInfoListe

Re: CALC: BASE-Abfrage in Tabelle bekommen

Verfasst: Di, 27.03.2012 11:02
von crush
Ich würde mich ja gern mehr selbst belesen und einarbeiten, aber ich habe bis jetzt keine geeignete Dokumentation gefunden, in der nicht nur beschrieben ist, wie ein Array initialisiert wird, sondern auch wieder es in einer Tabelle ausgegeben wird. Gibt es ein Nachschlagewerk, wo Funktionen wie ".getCellByPosition" und ähnliche beschrieben und dokumentiert sind? Ich habe bis jetzt C++, MATLAB, Java, SQL... programmiert und bin mit Visual- und StarBasic noch ein wenig ungeübt.

Gruß crush

Re: CALC: BASE-Abfrage in Tabelle bekommen

Verfasst: Di, 27.03.2012 11:38
von komma4
crush hat geschrieben:Ich würde mich ja gern mehr selbst belesen und einarbeiten
SDK
Andrews Makro-Dokument

Siehe auch das Coding von OOoDIL - zwar nicht viel dokumentiert, aber -so hoffe ich- selbsterklärend

Re: CALC: BASE-Abfrage in Tabelle bekommen

Verfasst: Di, 27.03.2012 13:49
von crush
Ok hier mein Versuch ohne dispatcher...

Code: Alles auswählen

dim MyArray(2,1000)
dim i as Integer
i = 1
rem ----------------------------------------------------------------------

If Not IsNull(ResultSet) Then
  While ResultSet.next
    MyArray(1,i) = ResultSet.getString(1)
    MyArray(2,i) = ResultSet.getString(2)
    i = i+1
  Wend
End If
osheet = thiscomponent.sheets(0)
osheet.getCellRangeByName("C2:D1000").setDataArray(MyArray())
Ich hänge im Moment noch daran, die Größe des Resultsets herauszubekommen, um das Array nicht überzudimensionieren. Aber selbst wenn, funktioniert es noch nicht, es kommt:
"BASIC Laufzeitfehler Type: com.sun.star.unoRuntimeException Message: ." mit verweis auf die letzte Zeile. Kann ich die Methoden nicht hintereinander hängen, sondern muss die Range noch extra definieren und dann erst .setDataArray hinten dranhängen oder was mache ich noch falsch?

Gruß crush

Re: CALC: BASE-Abfrage in Tabelle bekommen

Verfasst: Di, 27.03.2012 17:04
von Karolus
Hallo
Etwa so:

Code: Alles auswählen

dim MyArray(1000)
    i = -1

    If Not IsNull(ResultSet) Then
      While ResultSet.next
        i = i+1
        MyArray(i) = array( ResultSet.getString(1),ResultSet.getString(2))
      Wend
        redim Preserve MyArray( i )
    End If
    osheet = thiscomponent.sheets(0)
    osheet.getCellRangeByPosition(2,1,3,1+i).setDataArray(MyArray())
Karo

Re: CALC: BASE-Abfrage in Tabelle bekommen

Verfasst: Mi, 28.03.2012 07:17
von crush
Super, das hat geklappt. Aber warum bekomme ich bei getCellRangeByName eine Fehlermeldung?

Zwei kleine Fragen hätte ich noch: Mit "ResultSet = Statement.executeQuery(....." führe ich ja die Abfrage aus. Kann ich da nicht auch den Namen der Abfrage eintragen, die in der Datenbank abgespeichert ist, statt die query als String einzugeben?
Und gibt es die Möglichkeit "osheet = ThisComponent.sheets(7)" auch mit dem Tabellenblatt-Namen anzusprechen, statt die Nummer des Blattes einzutragen?

Gruß crush

Re: CALC: BASE-Abfrage in Tabelle bekommen

Verfasst: Mi, 28.03.2012 07:57
von Karolus
Hallo
crush hat geschrieben:Super, das hat geklappt. Aber warum bekomme ich bei getCellRangeByName eine Fehlermeldung?

Gruß crush
Woher sollen wir das wissen, wenn du zu bequem bist, den Quellcode zur Fehlermeldung hier zu posten und nichtmal die Fehlermeldung selbst postest.

Ich rate mal: dein ' .getCellRangeByName("bereichsadresse") hat nicht die passende Dimensionierung für ' .setDataArray( MyArray )

Karo

Re: CALC: BASE-Abfrage in Tabelle bekommen

Verfasst: Mi, 28.03.2012 08:35
von komma4
crush hat geschrieben:Abfrage eintragen, die in der Datenbank abgespeichert ist

Code: Alles auswählen

' Kontext holen
oDatenbankKontext = CreateUnoService ( "com.sun.star.sdb.DatabaseContext" )

' Datenquelle auswählen
' registrierte Datenquelle
oDatenquelle = oDatenbankKontext.getByName( "hsqldb_test1" )


sQuery = "qry_order_positionen_Parameter"

' Abfragen
oAbfragen = oDatenquelle.QueryDefinitions 
' gewünschte Abfrage vorhanden?
if ( oAbfragen.hasByName( sQuery) ) Then
' Abfrage holen
oAbfrage = oAbfragen.getByName( sQuery )


' SQL-Ausdruck von Abfrage entnehmen
 sQuery = oAbfrage.Command
 ' Verbindung zur DB herstellen
 oVerbindung = oDatenquelle.getConnection( , )
 ' Statement erzeugen
 oStatement = oVerbindung.createStatement()
 ' Abfrage absetzen
 oResultSet = oStatement.executeQuery( oAbfrage.Command )
crush hat geschrieben:mit dem Tabellenblatt-Namen anzusprechen

Code: Alles auswählen

ThisComponent.Sheets().getByName( "meineTabelle" )


Besorge Dir Andrews Makro-Dokument für die Grundlagen, und vom gleichen Author Andrews Base-Dokument

Re: CALC: BASE-Abfrage in Tabelle bekommen

Verfasst: Mi, 28.03.2012 09:48
von crush
Klappt alles wunderbar, nur bekomme ich eine Fehlermeldung: "Unzulässiger Wert oder Datentyp: Überlauf" wenn ich sehr viele Spalten an das Array übergebe:

Code: Alles auswählen

If Not IsNull(Kraftstoff) Then
  While Kraftstoff.next
    j = j+1
    MyArray2(j) = array( CInt(Kraftstoff.getString(1)),  CInt(Kraftstoff.getString(2)),  CInt(Kraftstoff.getString(3)), CInt(Kraftstoff.getString(4)),  CInt(Kraftstoff.getstring(5)),  CInt(Kraftstoff.getstring(6)),  CInt(Kraftstoff.getstring(7)),  CInt(Kraftstoff.getstring(8)),  CInt(Kraftstoff.getstring(9)),  CInt(Kraftstoff.getstring(10)),  CInt(Kraftstoff.getstring(11)),  CInt(Kraftstoff.getstring(12)),  CInt(Kraftstoff.getstring(13)),  CInt(Kraftstoff.getstring(14)),  CInt(Kraftstoff.getstring(15)))
  Wend	
  	redim Preserve MyArray2(j)
End If
Ist dem Compiler die Zeile zu lang, denn bei mir stehen alle hintereinander. Habe in dem Handbuch keinen Hinweis gefunden, wie ich den Code auf mehrere Zeilen verteilen kann. Gibt es neben .getString auch sowas wie getValue oder getInteger, habe schon einige probiert, aber diese Methoden scheint es für das Resultset nicht zu geben.


EDIT: Die Fehlermeldung hat sich erledigt: Eine der Spalten aus der DB-Tabelle war kein Integer. CDbl statt CInt sollte die Lösung, da habe ich aber das Problem, dass das Komma als Dezimaltrennzeichen nicht erkannt wird, und aus 52,50 wird 5250...

EDIT: Ich glaube ich weiß auch warum, denn wenn ich nur getString für diese Spalte ausgeben lasse, ohne das CDbl, dann steht da "52.50" mit "Punkt" statt "Komma", obwohl in Base die Abfrage in der Tabelle ein "52,20" mit "Komma" ausgibt. Das liegt dann wahrscheinlich an der Ländereinstellung. Kann man das bei einer Konvertierung des Strings berücksichtigen?

EDIT: OK selbst gefunden, Val(...getString) statt der ganzen anderen bringt den Erfolg.

Re: CALC: BASE-Abfrage in Tabelle bekommen

Verfasst: Fr, 30.03.2012 12:29
von crush
Hallo, wie kann man Calc dazu bringen, eine Datenbankdatei wiederzufinden, die man nur von einem Ordner in den nächsten verschoben hat. Bei mir findet CALC die Datenbank deswegen nicht mehr. Zu dem habe ich noch durch diverses rumprobieren und falsches abspeichern meine Abfragen gelöscht :(. Um das noch einmal zu vermeide meine Frage: Wie kann ich nach dem Verschieben der .odb-Datei diese wieder dem System bekannt machen?

EDIT: Hab die Datei wieder hergestellt bekommen, und unter "Datenquellen" und "registrierte Datenquellen" kann man die Datei unter dem neuen Speicherort einfach nochmal in die Liste eintragen. Schönes Wochenende

Grüße crush

Re: CALC: BASE-Abfrage in Tabelle bekommen

Verfasst: Fr, 30.03.2012 12:48
von komma4
Extras>Optionen...>OpenOffice.org Base>Datenbanken