Seite 1 von 1

Kontrollelemet extern auslesen?

Verfasst: Di, 03.05.2011 16:20
von geimist
Hallo,

bisher habe ich nur Kontrollelemente aus dem Formular (in OOoBase) auslesen müssen, aus dem ich auch das Makro gestartet habe und konnte daher über ThisComponent darauf zugreifen:

Code: Alles auswählen

oDoc = ThisComponent
oForm = oDoc.DrawPage.Forms.getByIndex(0) 
oFeld = oForm.getByName("NameKontrollelement")
sSuchwort = oFeld.text
Mein Versuch von außerhalb des Formulars darauf zu zugreifen schlägt bei "Drwpage" fehl:

Code: Alles auswählen

DatabaseContext = createUnoService("com.sun.star.sdb.DatabaseContext")
oDatenquelle = DatabaseContext.getByName("KKO")
oDoc = oDatenquelle.DatabaseDocument
oForms = oDoc.getFormDocuments()
oForm = oForms.getByName("config")

oSubForm = oForm.DrawPage.Forms.getByIndex(0) 'mit oSubForm meine ich das eigentliche Formular im Formularcontainer
oFeld = oSubForm.getByName("NameKontrollelement")
sSuchwort = oFeld.text
Wo ist der Haken???

Danke schon einmal

Re: Kontrollelemet extern auslesen?

Verfasst: Di, 03.05.2011 19:14
von DPunch
Aloha
geimist hat geschrieben:Wo ist der Haken???
Der Haken ist, dass Du mit ".getFormDocuments" nicht die echten Formulare ansprechen kannst, sondern nur die OOo API: DocumentDefinitions.
API hat geschrieben:Note that the DocumentDefinition does not denote the actual document (i.e. an object supporting the ::com::sun::star::frame::XModel interface), but only a shortcut to access and load those actual documents.
(Sprich: hier ist im Endeffekt nur der interne Name und Pfad zum "echten" Dokument gespeichert)

Ich verstehe auch gar nicht, was Du machen willst - selbst wenn Du das Formular auf diese Weise öffnen könntest, was willst Du denn bitteschön da auslesen?

Re: Kontrollelemet extern auslesen?

Verfasst: Di, 03.05.2011 19:28
von geimist
DPunch hat geschrieben:Ich verstehe auch gar nicht, was Du machen willst - selbst wenn Du das Formular auf diese Weise öffnen könntest, was willst Du denn bitteschön da auslesen?
Ich habe einen Dialog mit einem ImageControl. Das zuzuweisende Bild möchte ich aber nicht aus dem Dateisystem holen (unterschiedliche Pfade bei verschiedenen Anwendern / Fehlerpotential). Das einfachste wäre, ich könnte auf ein Bildfeld in der DB-Tabelle zugreifen (http://www.oooforum.de/viewtopic.php?f= ... 0b62da52d7).

Ein Notbehelf ist dieser: Man erstellt in einem Formular der DB ein Imagecontrol und speichert darin (!nicht als Verknüpfung!) das gewünschte Bild. Auf dieses gespeicherte Bild kann man durch abfragen dessen Url zugreifen und so auch einem Imagecontrol im Dialog zuweisen. Da ich das Formular aber nicht öffnen möchte, will ich "von auserhalb" darauf zugreifen.

Re: Kontrollelemet extern auslesen?

Verfasst: Di, 03.05.2011 22:07
von DPunch
Aloha
geimist hat geschrieben:Das einfachste wäre, ich könnte auf ein Bildfeld in der DB-Tabelle zugreifen
Ich wüsste nicht, dass das geht - da das Bild ja direkt als Binärdatei in die Datenbank geschrieben wird, bliebe höchstens, das Bild temporär wieder auf den jeweiligen Rechner zu schreiben.
geimist hat geschrieben:Ein Notbehelf ist dieser: Man erstellt in einem Formular der DB ein Imagecontrol und speichert darin (!nicht als Verknüpfung!) das gewünschte Bild.
Auf diese Weise ist das prinzipiell kein Problem (siehe auch Bild in Dialog).
geimist hat geschrieben:Da ich das Formular aber nicht öffnen möchte, will ich "von auserhalb" darauf zugreifen.
Das Auslesen der internen URLs, ohne das entsprechende Formular störend zu öffnen wäre entweder über das versteckte Öffnen oder über das Auslesen der content.xml des entsprechenden Formulars zu bewerkstelligen.
Das versteckte Öffnen ist die deutlich einfachere Methode, aber ansonsten hier mal ein Beispiel, wie das Auslesen ohne jegliches Öffnen funktionieren würde:
(die Bilder werden dabei über den Namen des ImageControls im Formular identifiziert).

Code: Alles auswählen

Function getImage(sImageName as String, sFormName as String, Optional DataSource as Object)
	If isMissing(DataSource) Then
		DataSource = thisDatabaseDocument
	End If
	If NOT DataSource.FormDocuments.hasByName(sFormName) Then Exit Function
	oForm = DataSource.FormDocuments.getByName(sFormName)
	sPersistantName = oForm.PersistentName
	oForms = DataSource.getDocumentSubStorage("forms",1)
	oForm = oForms.getByName(sPersistantName)
	If NOT oForm.hasByName("Pictures") Then Exit Function
	oImages = oForm.getByName("Pictures")
	oInputStream = oForm.openStreamElement("content.xml",1)
	oTextStream = createUnoService("com.sun.star.io.TextInputStream")
	oTextStream.InputStream = oInputStream
	aDelimiter = Array(ASC("<"))
	Do While NOT oTextStream.isEOF
		sLine = oTextStream.readString(aDelimiter,True)
		nStart = Instr(sLine,"image-frame form:name=")
		If nStart > 0 Then
			nStart = nStart + 23
			nEnd = Instr(nStart,sLine,"""")
			sResultingPicName = Mid(sLine,nStart,nEnd-nStart)
			If sResultingPicName = sImageName Then				
				nStart = Instr(sLine,"/")+1
				nEnd = Instr(nStart,sLine,"""")
				sURL = Mid(sLine,nStart,nEnd-nStart)
				Exit Do
			End If
		End If
	Loop
	oTextStream.closeInput
	oImage = oImages.getByName(sURL)
	oGraphicProvider = createUnoService("com.sun.star.graphic.GraphicProvider")
	Dim args(1)as new com.sun.star.beans.PropertyValue
	args(0).Name  = "InputStream"
	args(0).Value = oImage.InputStream 
	getImage = oGraphicProvider.queryGraphic(args)
End Function
Anwendung:

Code: Alles auswählen

Sub Main
	oMeinImageControl = meinDialog.getControl("meinImageControlImDialog") 'z.B. "ImageControl1"
	sNameDesImageControlsImFormular = "NameMeinesImageControlsImFormular" 'am besten mit sprechendem Namen, z.B. "Bild1"
	sNameDesFormularsMitDenEmbeddedImages = "NameDesFormulars" 'z.B. "Formular1"
	'Verwendung aus demselben .odb File heraus:
	oMeinImageControl.Model.Graphic = getImage(sNameDesImageControlsImFormular,sNameDesFormularsMitDenEmbeddedImages)
	'*oder: aus einem beliebigen File:
	'*oDatabaseContext = CreateUNOService("com.sun.star.sdb.DatabaseContext")
	'*oDataSource = oDatabaseContext.getByName("meineRegistrierteDatenbank") 'bzw die URL der .odb
	'*oMeinImageControl.Model.Graphic = getImage(sNameDesImageControlsImFormular,sNameDesFormularsMitDenEmbeddedImages,oDataSource.DatabaseDocument)
End Sub
Edit: Nochmal daraufhin angepasst, dass man es von jedem beliebigen Dokument aus benutzen kann (in diesem Fall muss das DatabaseDocument mit übergeben werden).

Re: Kontrollelemet extern auslesen?

Verfasst: Mi, 04.05.2011 17:03
von geimist
Vielen Dank schon mal an dieser Stelle.

Leider kommt es jetzt in dieser Zeile (der Funktion)

Code: Alles auswählen

...
oForm = oForms.getByName(sPersistantName)
...
zu diesem Fehler:
Bild
:?

Re: Kontrollelemet extern auslesen?

Verfasst: Mi, 04.05.2011 17:47
von DPunch
Aloha

Der Fehler deutet darauf hin, dass Du das Formular beim Ausführen des Makros im Bearbeitungsmodus geöffnet hast - da es Dir ja darum ging, das Formular gerade nicht geöffnet zu haben, habe ich darauf auch keine Rücksicht genommen (das Formular kann trotzdem z.B. per Doppelklick im schreibgeschützten Modus geöffnet werden).

Folgende Zeile allerdings muss ganz ans Ende der Funktion:

Code: Alles auswählen

	oImage.InputStream.closeInput
Mir ist aufgefallen, dass das Formular sonst nach einmaliger Ausführung des Makros die Bearbeitung verweigert, da immer noch ein offener Stream auf das Package zugreift.

Desweiteren empfehle ich bei der Anwendung (Prozedur "Main") statt

Code: Alles auswählen

	oMeinImageControl.Model.Graphic = getImage(sNameDesImageControlsImFormular,sNameDesFormularsMitDenEmbeddedImages,oDataSource.DatabaseDocument)
noch eine Sicherheitsabfrage der Art

Code: Alles auswählen

	oImage = getImage(sNameDesImageControlsImFormular,sNameDesFormularsMitDenEmbeddedImages,oDataSource.DatabaseDocument)
	If NOT isEmpty(oImage) Then
		oMeinImageControl.Model.Graphic = oImage
	End If
um nicht mit Fehlermeldungen belästigt zu werden, wenn man z.B. einen nicht-existenten Bildnamen übergeben hat.

Re: Kontrollelemet extern auslesen?

Verfasst: Mi, 04.05.2011 17:56
von geimist
ist ja peinlich...

Das Formular war lediglich deshalb auf, weil ich nach dem Namen des Steuerelementes nachgesehen habe.

Formular zu und Makro läuft UND Bild ist da!
Bitte entschuldige, dass du jetzt noch nach einen 'Ausweg' gesucht hast.

Vielen Dank für deine Hilfe - Problem gelöst ;-)

Re: Kontrollelemet extern auslesen?

Verfasst: Mi, 04.05.2011 18:19
von DPunch
geimist hat geschrieben:Bitte entschuldige, dass du jetzt noch nach einen 'Ausweg' gesucht hast.
Die zusätzlichen Codeschnipsel haben nur bedingt was mit dem bei Dir aufgetretenen Fehler zu tun, den konnte ich ja klar zuordnen.
Die anderen Anmerkungen sind allerdings durchaus von Bedeutung, daher hier nochmal die "stabilere" Version:

Code: Alles auswählen

Function getImage(sImageName as String, sFormName as String, Optional DataSource as Object)
	If isMissing(DataSource) Then
		DataSource = thisDatabaseDocument
	End If
	If NOT DataSource.FormDocuments.hasByName(sFormName) Then Exit Function
	oForm = DataSource.FormDocuments.getByName(sFormName)
	sPersistantName = oForm.PersistentName
	oForms = DataSource.getDocumentSubStorage("forms",1)
	On Error GoTo FormOpenError
	oForm = oForms.getByName(sPersistantName)
	On Error GoTo UndefinedError
	If NOT oForm.hasByName("Pictures") Then Exit Function
	oImages = oForm.getByName("Pictures")
	oInputStream = oForm.openStreamElement("content.xml",1)
	oTextStream = createUnoService("com.sun.star.io.TextInputStream")
	oTextStream.InputStream = oInputStream
	aDelimiter = Array(ASC("<"))
	Do While NOT oTextStream.isEOF
		sLine = oTextStream.readString(aDelimiter,True)
		nStart = Instr(sLine,"image-frame form:name=")
		If nStart > 0 Then
			nStart = nStart + 23
			nEnd = Instr(nStart,sLine,"""")
			sResultingPicName = Mid(sLine,nStart,nEnd-nStart)
			If LCase(sResultingPicName) = LCase(sImageName) Then				
				nStart = Instr(sLine,"/")+1
				nEnd = Instr(nStart,sLine,"""")
				sURL = Mid(sLine,nStart,nEnd-nStart)
				Exit Do
			End If
		End If
	Loop
	oTextStream.closeInput
	If Len(sURL) = 0 Then Exit Function
	If NOT oImages.hasByName(sURL) Then
		Exit Function
	End If
	On Error Resume Next
	oImage = oImages.getByName(sURL)
	oGraphicProvider = createUnoService("com.sun.star.graphic.GraphicProvider")
	Dim args(1)as new com.sun.star.beans.PropertyValue
	args(0).Name  = "InputStream"
	args(0).Value = oImage.InputStream 
	getImage = oGraphicProvider.queryGraphic(args)
	oImage.InputStream.closeInput
	Exit Function
	FormOpenError:
	MsgBox ("Auf das Formular konnte nicht zugegriffen werden",48,"Fehler")
	Exit Function
	UndefinedError:
	If NOT isNull(oTextStream) Then
		oTextStream.closeInput
	End If
	MsgBox ("Es ist ein allgemeiner Fehler aufgetreten",48,"Fehler")
End Function

Re: Kontrollelemet extern auslesen?

Verfasst: Mi, 04.05.2011 21:20
von geimist
Vielen Dank :D