[gelöst] per Basic-Makro den Typ einer Variablen ermitteln

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

Moderator: Moderatoren

StePfl
**
Beiträge: 47
Registriert: Mo, 04.07.2016 17:16

[gelöst] per Basic-Makro den Typ einer Variablen ermitteln

Beitrag von StePfl »

Immer wieder bleibe ich hängen, weil ich den genauen Typ einer Variablen (so wie im Makroeditor - BeobachterFenster unter Typ dargelstell) kenne
und nicht vorhandene/falsche Methoden/ Eigenschaften versuche zu verwenden.

Ich kenne die Funktionen "TypeName", "VarType" und "isUnoStruct" sowie die Eigenschaft "ImplementationName" .... aber damit lassen sich nicht alle Typen/Strukturen ermitteln (z.B. die RangeAddress-Struktur).

Intern müssenaber diese Werte vorliegen, denn im "Beobachter"-Bereich werden diese in der "Tyü"-Spalte aufgeführt

mein bisheriger Ansatz finde ich eher unbefriedigend:

Gruß StePfl

Code: Alles auswählen

Function TypeOfVar(optional Var)
	'
	
	'==== Testvorgaben"
	' var = "Tabelle4.A1:c15"
	' var = thiscomponent.sheets().getByName("Tabelle4").getcellrangebyname("A1:C15")


	if ismissing(var) then
		var = thiscomponent.currentselection
	endif


	iVarTyp = VarType(var)
	sVarTyp = TypeName(var)



	' Var ist ein "Object"
	if iVarTyp = 9 then 

		hlp1 = ""

		' Prüfen, ob es sich um eine UnoRangeAddress-Struktur handelt
		on Error resume next
			hlp1 = isnumeric(var.endrow) and isnumeric(var.sheet)
			on Error goto 0
			if hlp1 = true Then hlp1 = "UnoRangeAddress"

		' Prüfen, ob das Object einen ImplementationName hat
		on Error resume next
			hlp1 = var.ImplementationName
		on Error goto 0
		
		
		if hlp1 = "ScCellRangeObj"  then
			sVarTyp = "ScCellRangeObj"
		elseif hlp1 = "ScCellObj" then
			sVarTyp = "ScCellObj"
		elseif hlp1 = "ScTableSheetObj" then
			sVarTyp = "ScTableSheetObj"
		elseif hlp1 = "UnoRangeAddress" then
			sVarTyp = "UnoRangeAddress"
		else
			' hier können weitere ObjektTypen eingetragen werden
			sVarTyp = "Objekt - ohne Identifikation"
		endif

	' "var" ist ein String"
	elseif iVarTyp = 8	then 

		' Prüfung, ob "var" einen gültigen AdressString enthält
		on Error resume next
			adr = Split(Var)
			hlp1 = thiscomponent.sheets().getByName(adr(0)).getcellrangebyname(adr(1))
		on Error goto 0
		sVarTyp = "RangeAddressString"
		
		' ... oder weitere Typerkennungen
	endif

	TypeOfVar = sVarTyp	

end function
Zuletzt geändert von StePfl am Sa, 17.06.2017 08:52, insgesamt 1-mal geändert.
Stephan
********
Beiträge: 12369
Registriert: Mi, 30.06.2004 19:36
Wohnort: nahe Berlin

Re: per Basic-Makro den Typ einer Variablen ermitteln

Beitrag von Stephan »

Es wird Dir nicht gefallen das ich mit einer Gegenfrage antworte, aber: Was willst Du eigentlich erreichen?

Um nur die richtigern Methoden auf Objekte loszulassen oder die richtigen Eigenschaften abzufragen verwendet man zur vorherigen Prüfung i.A. SupportsService:
http://www.openoffice.org/api/docs/comm ... rtsService

Beispiele:

Ist das aktuelle Dokument tatsächlich ein Tabellendokument:

Code: Alles auswählen

If ThisComponent.supportsService("com.sun.star.sheet.SpreadsheetDocument") then
	'tue was
End iF
Welche Selektion im Tabellendokument ist existent:

Code: Alles auswählen

selektion = ThisComponent.getCurrentSelection()
If selektion.supportsService("com.sun.star.sheet.SheetCell") Then
	'tue was für Zelle passt
Elseif selektion.supportsService("com.sun.star.sheet.SheetCellRange") Then
	'tue Was für einen Bereich passt
Elseif selektion.supportsService("com.sun.star.sheet.SheetCellRanges") Then
	'tue was für mehrere Bereiche passst (i.A. interiere durch die Unterbereiche)
Else
	'...
End If
Das geht praktisch für jedes Objekt bzw. Objektvariable, denn Du weißt ja quasi vorher welche(n) Service(s) das Objekt erfüllen muss wenn es das Richtige ist.


Gruß
Stephan
StePfl
**
Beiträge: 47
Registriert: Mo, 04.07.2016 17:16

Re: per Basic-Makro den Typ einer Variablen ermitteln

Beitrag von StePfl »

SUPER!

das "SupportsService" kannte ich nicht .... deshalb mein Lösungsversuch! .. ABER:

Code: Alles auswählen

If ThisComponent.supportsService("com.sun.star.sheet.SpreadsheetDocument") then
	'tue was
End iF
Hier frägst du nach, ob der Typ "com.sun.star.sheet.SpreadsheetDocument" vorliegt....
Ich hatte nach einer Funktion gesucht, die mir auf Anfrage sagt, dass "var" vom Typ "com.sun.star.sheet.SpreadsheetDocument" ist ....
Also die umgekehrte Richtung.


Mich hatte einfach interessiert, ob/wie man die Information, die im "Beobachtungsfenster" vorliegt auch Programmintern erfahren und ggf. nutzen kann...
Ist eher ein "Weiterlernen" wollen....

Zum Beispiel die Idee:
Gestaltung einer Sub "RangeOfVar", die ein RangeObjekt liefert, egal in welcher Form in Var die AdressInformation vorliegt.

Immer wieder stelle ich fest, dass das Programmieren mit LO.Basic meinen Denkrahmen sprengt und ich keine Ahnung habe, was es alles gibt.
Bei meinen Programm"basteleien", stelle ich regelmäßig fest, dass ich sehr viel mehr Zeit dafür benötige, den/einen passenden Programimierweg zu finden, als für das eigentliche nurmerische, datenstrukturelle Problem.

KLAR - es wäre besser, die Programmiersprache RICHTIG zu lernen - leider sprengt das meistens meinen Kopf und auch den verfügbaren Zeitrahmen.

So versuche ich, hier Horizonterweiterung zu finden... und stelle hier immer wieder solche Fragen

Danke für deine immer wieder erlebbare Gedult und dein interessiertes Nachfragen,
lieben Gruß
StePfl
Stephan
********
Beiträge: 12369
Registriert: Mi, 30.06.2004 19:36
Wohnort: nahe Berlin

Re: per Basic-Makro den Typ einer Variablen ermitteln

Beitrag von Stephan »

Hier frägst du nach, ob der Typ "com.sun.star.sheet.SpreadsheetDocument" vorliegt....
Ich hatte nach einer Funktion gesucht, die mir auf Anfrage sagt, dass "var" vom Typ "com.sun.star.sheet.SpreadsheetDocument" ist ....
Also die umgekehrte Richtung.
Du kannst natürlich auch schreiben:

Code: Alles auswählen

var = ThisComponent
If var.supportsService("com.sun.star.sheet.SpreadsheetDocument") then
	'tue was
End iF
oder die Prüfung in einer Funktion kapseln:

Code: Alles auswählen

Sub Abfragen()
	var = ThisComponent
	If ist_tabellendokument(var) Then
		'tue was
	End If
End Sub

Function ist_tabellendokument(xyz)
	ist_tabellendokument = xyz.supportsService("com.sun.star.sheet.SpreadsheetDocument")
End Function
das macht aber u.U. Probleme wenn var kein Objekt enthält und deshalb am Anfang meine Frage was Du machen willst, denn mir ist ohne konkrete Frage momentan kein Praxisfall eingängig wo es solche Problem geben kann wenn der Inhalt von var im Normalfall ein Objekt repräsentiert.

Woher soll denn var kommen WENN die Frage heißt ob var ein Tabellendokument repräsentiert? in Praxis doch eigentlich nur wenn überhaupt ein Objekt in var steckt, also z.B. das ThisComponent oder auch das Dokumentobjekt eines zu öffnenden Dokuments, z.B.:

Code: Alles auswählen

url = converttourl("C:\test.sxw")
var = StarDesktop.loadComponentFromURL(url, "_blank", 0, Array())
Mir ist eigentlich kein Code vorstellbar bei dem var im gewünschten Normalfall eine Objektvariable ist und im Falle das während der Laufzeit des Makros etwas schief läuft plötzlich nicht mehr, denn wenn ich schreibe:

Code: Alles auswählen

var = 3
weiß ich vorher das var kein Objekt enthält also auch kein Tabelklendokumen-Objekt enthalten kann. WEnn ich hingegen schreibe:

Code: Alles auswählen

var = ThisComponent.getCurrentSelection()
enthält var (eigentlich) IMMER ein Objekt, egal Welches (z.B. Zelle, Text, Grafik, Rahmen, ...)


Du musst also ein praktisches Beispiel liefern was Du befürchtest was mit var falsch laufen soll. "praktisch" meint das der Code nicht schon ansich sichtbar falsch ist denn das ist kein Relevanter Fall, insofern man seine Energie bei Programmieren ja darein steckt Fehler im Code zu vermeiden und nicht darein eine möglichst umfassende Fehlerroutine zu schreiben in der Absicht den eigentliche Code dadurch völlig fehlerhaft schreiben zu dürfen (keine Ahnung wie ich das besser ausdrücken kann).


Gruß
Stephan
StePfl
**
Beiträge: 47
Registriert: Mo, 04.07.2016 17:16

Re: per Basic-Makro den Typ einer Variablen ermitteln

Beitrag von StePfl »

Stephan: sorry - stimmt!

ich hatte mir eine Function "getClosedRangeOfCell" geschrieben, die mir bei Übergaben einer Adresse (Cell-Objekt oder Range-Objekt) den geschlossenen Zellbereich als Range zurück gibt. Nun bin ich an einer anderen Stelle darüber gestolpert, dass ich statt einem "CellObjekt" ein "RangeAddress-Objekt" übergaben hatte, die ich aus einer anderen Function erhalten hatte. ... hat natürlich nicht funktioniert.

Die liefernde Funktion kann/will ich aber nicht ändern, da sie an mehreren Stellen aufgerufen wird und dort das RangeAdress-Objekt als Ergebnis erwartet/gebraucht wird.

Die Idee war nun, dass ich "getClosedRangeOfCell" so aufbohre, dass es von sich aus erkennt, um welche "Objekt"-Art es sich bei dem übergebenen Parameter handelt - also entweder ein Cell-/RangeObjekt, ein RangeAddress-Objekt oder eventuell sogar eine TextAddresse in Stringform - und daraus den richtigen Objekt-Typ (oder eine Fehlermeldung) generiert und weiterarbeitet.

Dafür sollte "TypeOfVar" Hilfestellung liefern .... quasi als verallgemeinerte Hilfsroutine.

Leider erkennt zwar "VarType", wenn es sich um ein Objekt handelt, aber nicht um welchen Typ von Objekt.
Der Umweg über "ImplementationName" hat beim "RangeAddress-Objekt" nicht funktioniert - ist ja ein "Uno..."-Objekt
Das habe ich nun versucht mit dem Test, ob das Objekt die Eigenschaften "sheet" und "endRow" hat abzufangen - mit dem Wissen, dass ich wieder nur im Nebel herumstochere und vermutlich weitere, zusätzliche Fehlerquellen erzeuge.

Also habe ich hier die Frage gestellt, ob es eine generelle Funktion gibt, die mir bei "getVarTye(var)" den ObjektTyp von "var" zurückliefert.
Im System muß der ObjektTyp bekannt sein, denn im "Beobachter"-Bereich" gibt es die Spalte "Typ" und dort stehen die gesuchten Bezeichnungen ja drin.

Ich hoffe, dass ich nun meine Idee deutlich genug erklärt habe - aber - vielleicht will ich nur Unmögliches (oder Unsinniges).
UND - natürlich kann ich das og. Problem durch saubere Programmierung und Dokumentation bereinigen und vermeiden... DAS IST MIR KLAR.

Vielen Dank fürs Lesen und Kommentieren/Gegenfragen.

herzlichen Gruß
Stefan
Stephan
********
Beiträge: 12369
Registriert: Mi, 30.06.2004 19:36
Wohnort: nahe Berlin

Re: per Basic-Makro den Typ einer Variablen ermitteln

Beitrag von Stephan »

Die Idee war nun, dass ich "getClosedRangeOfCell" so aufbohre, dass es von sich aus erkennt, um welche "Objekt"-Art es sich bei dem übergebenen Parameter handelt - also entweder ein Cell-/RangeObjekt, ein RangeAddress-Objekt oder eventuell sogar eine TextAddresse in Stringform - und daraus den richtigen Objekt-Typ (oder eine Fehlermeldung) generiert und weiterarbeitet.
Naja, nun hast Du ja schon alle wesentlichen Infos und müsstest die nur kombinieren und ein wenig erweitern, dann hättest Du die Lösung, dier z.B. so aussehen könnte:

Code: Alles auswählen

Sub Main
	var = ThisComponent.Sheets(0).getCellByPosition(0,1)

	'alternativ (zum Testen):
	'var = ThisComponent.Sheets(0).getCellRangeByPosition(0,1,2,3)
	'var = ThisComponent.Sheets(0).getCellRangeByPosition(0,1,2,3).getRangeAddress()
	'var = "Tabelle1.A1:A10"

	Msgbox meineFunktion(var)
End Sub

Function meineFunktion(var)
	
	If IsUnoStruct(var) Then
		'var ist RangeAddress - tue was
		erg = "CellRangeAddress"
		meineFunktion = erg
		Exit Function
	End If
	
	On Error Goto keinText
	tmp = Split(var, ".")
	On Error Goto 0
	
	If UBOUND(tmp()) = 1 Then
		'es könnte Textadresse sein, prüfen wir den ersten Teil
			If ThisComponent.Sheets.hasByName(tmp(0)) Then
				'die Tabelle existiert
				'var ist Textadresse - tue was
				erg = "Textadresse"
			End If
		Else
			'dieser Fall existiert nicht, denn Text muss TextAdresse sein
	End If
	
	meineFunktion = erg
	Exit Function
	
	keinText:
	var2 = var
	If var2.supportsService("com.sun.star.sheet.SheetCell") Then
			'var ist ein Zellobjekt - tue was
			erg = "Cell"
		ElseIf var2.supportsService("com.sun.star.sheet.SheetCellRange") Then
			'var ist Range-Adresse - tue was
			erg = "CellRange"
	End If
	
	meineFunktion = erg
End Function
Hierbei gilt das von mir schon Gesagte, nämlich das die Programmierung ansich nicht grundsätzlich falsch sein darf, denn in vorstehendem Beispiel wird mitnichten Alles geprüft sondern nur ob var entwder ein Cell-Objekt, ein CellRange-Objekt, eine CellRange-Adresse oder eine Textadresse ist, d.h. es ist beispielsweise sicherzustellen das ein String der als var übergeben wird auch tasächlich nur eine Textadresse ist, denn irgendein beliebiger Text funktioniert nicht, weil nur teilweise geprüft wird das der Text eine Textadresse ist.

UND - natürlich kann ich das og. Problem durch saubere Programmierung und Dokumentation bereinigen und vermeiden... DAS IST MIR KLAR.
Dann solltest Du das auch tun. Die vorstehend von mir gepostete Lösung halte ich für rein akademisch und würde sie so in Praxis nicht verwenden, weil sie einfach unnötig kompliziert ist.



Gruß
Stephan
StePfl
**
Beiträge: 47
Registriert: Mo, 04.07.2016 17:16

Re: per Basic-Makro den Typ einer Variablen ermitteln

Beitrag von StePfl »

Dann solltest Du das auch tun. Die vorstehend von mir gepostete Lösung halte ich für rein akademisch und würde sie so in Praxis nicht verwenden, weil sie einfach unnötig kompliziert ist.
STIMMT ....

Es hat mich einfach interessiert - danke!
Und an deinem BeispielCode kann ich außerdem lernen, wie DU so etwas (programmtechnisch) gestalten würdest ...

nochmals Danke - und bis zum nächsten Mal

Gruß
Stepfl
Stephan
********
Beiträge: 12369
Registriert: Mi, 30.06.2004 19:36
Wohnort: nahe Berlin

Re: [gelöst] per Basic-Makro den Typ einer Variablen ermitteln

Beitrag von Stephan »

Und an deinem BeispielCode kann ich außerdem lernen, wie DU so etwas (programmtechnisch) gestalten würdest ...
Das Problem ist das die Lösung hier im Konkreten nicht ganz systematisch sein kann, weil man bestimmte Fehlermeldungen nicht unterdrücken kann und deshalb diese Fehlermeldungen durch die konkrete Gestaltung der Funktion ausschließen muss.
Das genannte Lösungsbeispiel arbeitet für 2 Typen der Variable nach dem Ausschlussprinzip und nur für die zwei anderen Typen wird quasi direkt unterschieden.

Verständlicher wäre eine Lösung die direkt zwischen den 4 Fällen der Variable unterscheidet, also eine einzige if-Then-ElseIf-Else Konstruktion.


Gruß
Stephan
Antworten