# VB mehfach Split



## emilio20 (31 Dezember 2014)

Hallo
ich bin grade dabei Philips HUE Lampen in eine Wicc TIA V13 Script mit einzubinden. Das Schalten der Lampen Funktioniert soweit. Ich möchte gerne die Aktuelle Farbe der Lampen über ein Script auslesen. Dies funktioniert auch schon soweit. Allerdings habe ich noch das Probleme den result zu zuerspliten.

Ich möchte den result in einem 2 Dimensionalen Array zerlegen. Wobei der Split nach"," in die i Ebene  und der Split ":" in die j Ebene des Array zerleget werden soll.

Kann mir jemand helfen wie ich den weiterenn Split durchführen kann ?





```
field = Split(result,",")
    
    For i=0 To 1
        field(i) = Replace(field(i), "{", "")
        field(i) = Replace(field(i), "}", "")
        field(i) = Replace(field(i), " ", "")
        
        HiField(j, i) = field(i)
        
    
    Next
```


Ergeniss   result ohne Split 

```
{"state": {"on":false,"bri":100,"hue":32000,"sat":79,"effect":"none","xy":[0.3595,0.4516],"alert":"none","colormode":"hs","reachable":true}, "type": "Color light", "name": "LivingColors 1", "modelid": "LLC011","uniqueid":"00:17:88:01:00:c0:8a:e8-0b", "swversion": "66013452", "pointsymbol": { "1":"none", "2":"none", "3":"none", "4":"none", "5":"none", "6":"none", "7":"none", "8":"none" }}
```



Ergebniss: Split nach ","

```
"state":"on":false
"bri":100
"hue":32000
"sat":79
"effect":"none"
"xy":[0.3595
0.4516]
"alert":"none"
"colormode":"hs"
"reachable":true
"type":"Colorlight"
"name":"LivingColors1"
"modelid":"LLC011"
"uniqueid":"00:17:66:02:00:c0:8c:e8-0b"
"swversion":"66013452"
"pointsymbol":"1":"none"
"2":"none"
"3":"none"
"4":"none"
"5":"none"
"6":"none"
```


----------



## emilio20 (2 Januar 2015)

Kein VB Experte hier der eine Lösung weiß ?


----------



## RONIN (3 Januar 2015)

emilio20 schrieb:


> Hallo
> Ich möchte den result in einem 2 Dimensionalen Array zerlegen. Wobei der Split nach"," in die i Ebene  und der Split ":" in die j Ebene des Array zerleget werden soll.


 Also bevor du deinen Beitrag nicht um das Beispiel für deinen String erweitert hast hatte ich keine Ahnung was der Satz heißen sollte...

Hier ein Vorschlag... (nicht ausgetestet, nur runtergetippt)
Sind sicher noch Fehler drin, aber vielleicht reicht das schon um dich auf eine Spur zu bringen.
Ich bin mir aber auch nicht sicher ob ich deinen Satz richtig verstanden habe.

```
Dim result
Dim field_K, field_D
Dim i, j
Dim x
DIM Cnt1, Cnt2
Dim HiField()


field_K = Split(result,",")			'Split nach ","

Cnt1 = 0					'Finde Größenparameter für das Array
For i = 0 To Ubound(field_K)			'Finde größte Anzahl an Substrings für ":"
	
	x = field_K(i)
	Cnt2 = Len(x) - Len(Replace(x, ":", ""))  + 1 	'Anzahl der Zeichen ":" + 1
	If Cnt2 > Cnt1 Then				'Gerade "uniqueid" besteht aus vielen Teilen
		Cnt1 = Cnt2
	End If
Next

Redim HiField(Ubound(field_K),Cnt1)		'HiField neu dimensioneren

For i=0 To Ubound(field_K)
	
	x = field_K(i)
	x = Replace(x, "{", "")			'Entfernen nicht gewünschter Zeichen
        x = Replace(x, "}", "")
        x = Replace(x, " ", "")

	field_D = Split(x,":")			'Split nach ":"

	For j=0	TO UBound(field_D)		'Teile des Split ":" in das Array kopieren
		
		HiField(i,j) = field_D(j)

	Next

Next
```

Sollte (möglicherweise ) ein Array HiField(19,8 )ergeben...

j0j1j2j3j4j5j6j7j8ji00"state""on"falsei01"bri"100i12"uniqueid""0017660200c08ce8-0b"


----------



## Jochen Kühner (3 Januar 2015)

vlt. kann ja das verwendet werden: https://code.google.com/p/vba-json/issues/attachmentText?id=15&aid=150001000&name=jsonlib.cls&token


----------



## emilio20 (3 Januar 2015)

@RONIN genau das was ich wollte. Funktioniert. Vielen Dank *ACK*

Jetzt möchte ich ja ach was dazulernen zu VB.
Was hat es mir den neu Dimensionieren auf sich ?

Könnstes du mir diesen Teil noch mal genauer erklären ?


```
For i = 0 To Ubound(field_K)            'Finde größte Anzahl an Substrings für ":"
    
    x = field_K(i)
    Cnt2 = Len(x) - Len(Replace(x, ":", ""))  + 1     'Anzahl der Zeichen ":" + 1
    If Cnt2 > Cnt1 Then                'Gerade "uniqueid" besteht aus vielen Teilen
        Cnt1 = Cnt2
    End If
Next
```


----------



## RONIN (3 Januar 2015)

Wundert mich eigentlich dass das so ohne weiteres funktioniert.... 

 Zum Neu-Dimensionieren des Array. Ich weiß am Anfang noch nicht wie groß die beiden Ebenen des Array sein müssen. Daher wird es zunächst als unspezifiziert deklariert und sobald die richtigen Werte bekannt sind,  neu dimensioniert. 

Zum korrekten dimensioneren des Arrays muss ich im Vorhinein schon herausfinden wie hoch die größte Anzahl an Substrings nach dem Split-":" ist. 

Bei einem eindimensionalen Array kann man das Array on the fly mit "Redim Preserve" nachdimensionieren. Bei mehrdimensionalen Array geht das nur mehr schwer. Daher finde ich vorher schon heraus wie groß das Array jeweils sein muss.

Zum von angesprochenen Teil:
Es wird jeder Substring aus dem Split-", " durchgegangen und bestimmt in wieviele Teile dieser String nach dem Split-":" zerfallen wird.  Die größte Anzahl ist die Dimensionierung für das Array. 

Len(x) - Len(Replace(x, ":", ""))
Dieser Teil gibt zurück wie oft ":"  im String enthalten war.  Dieser Wert + 1 ist gleich der Anzahl der Substrings die man mit Split-":"  bekommen würde. Ich hätte hier auch mit Split und Ubound arbeiten können, aber mir gefiehl das besser. 

Das ist jetzt halt nur eine Lösung für das was du wolltest, wahrscheinlich gibst noch bessere.


----------



## wolfi_by (3 Januar 2015)

Hallo!
evtl .split().split()... Probieren oder regex... Ansonsten mal bei vb-paradise.de vorbeischaun
gruss


----------



## emilio20 (6 Januar 2015)

Hallo
ich möchte gerne 1 wert in die Funktion übergeben und 3 werte aus dem Script zurückgeben. Leider Funktioniert dies nicht. Ich habe gelesen das ich hierfür eine Funktion verwenden muss keinen Sub. Ändere ich den Sub in ein  Funktion kommt der Fehler 

,Die Funktion Hue_Farbe_read wurde fehlerhaft übersetzt. Wenn Sie die Funktion im Editor übersetzen, erhalten Sie detaillierte Informationen.,1,0,00:44:30



```
Function Hue_Farbe_read(ByRef light, ByRef bri, ByRef hue, ByRef sat)


Dim IP, Username
Dim result
Dim field_K, field_D
Dim i, j
Dim x
Dim Cnt1, Cnt2
Dim fso, f, ts, Path
Dim ausgabe
Dim ausgabedatei
Dim MyURL , postData 
Dim winHttpReq 
Dim HiField()
Set winHttpReq = CreateObject("WinHttp.WinHttpRequest.5.1")

i=0
j=0


IP=SmartTags("DB59 PHILIPS HUE_IP")
Username=SmartTags("DB59 PHILIPS HUE_username")

MyURL = "http://"&IP&"/api/"&Username&"/lights/" & light &""


winHttpReq.Open "GET", MyURL, False
winHttpReq.Send 

result = winHttpReq.ResponseText


field_K = Split(result,",")            'Split nach ","

Cnt1 = 0                    'Finde Größenparameter für das Array
For i = 0 To UBound(field_K)            'Finde größte Anzahl an Substrings für ":"
    
    x = field_K(i)
    Cnt2 = Len(x) - Len(Replace(x, ":", ""))  + 1     'Anzahl der Zeichen ":" + 1
    If Cnt2 > Cnt1 Then                'Gerade "uniqueid" besteht aus vielen Teilen
        Cnt1 = Cnt2
    End If
Next

ReDim HiField(UBound(field_K),Cnt1)        'HiField neu dimensioneren

For i=0 To UBound(field_K)
    
    x = field_K(i)
    x = Replace(x, "{", "")            'Entfernen nicht gewünschter Zeichen
        x = Replace(x, "}", "")
        x = Replace(x, " ", "")

    field_D = Split(x,":")            'Split nach ":"

    For j=0    To UBound(field_D)        'Teile des Split ":" in das Array kopieren
        
        HiField(i,j) = field_D(j)
        
    Next

Next


 bri= HiField(1, 1)
 hue= HiField(2, 1)
 sat= HiField(3, 1)



End Function
```


----------



## PN/DP (6 Januar 2015)

emilio20 schrieb:


> ```
> Function Hue_Farbe_read(ByRef light, ByRef bri, ByRef hue, ByRef sat)[/COLOR]
> ...
> End Function
> ```


Ich kenne TIA-VBS nicht - kennt das tatsächlich Function-Deklaration, End Function und ByRef??? 
Zumindest fehlt in Deinem Skript die Zuweisung eines Rückgabewertes an den Funktionsname.

Was für ein WinCC TIA V13 programmierst Du eigentlich? Advanced oder Professionell? Bzw. in welchem System läuft Dein VB-Skript?

Harald


----------



## faust (6 Januar 2015)

Hallo emilio,

grundsätzliches zu Scripten (ob WinCC Advanced oder VBS generell):
1. Die Rückgabe von Werten kann nur durch eine Funktion (Function) erfolgen.
2. Eine Funktion kann prinzipiell nur EINEN Wert zurückgeben.
3. Dieser Rückgabewert kann auch ein (mehrdimensionales) Array sein.
4. Die von dir beim Funktionsaufruf angegebenen Variablen sind Parameter, die an die Funktion ÜBERGEBEN werden.
5. Den Rückgabewert muss man wie folgt behandeln:
    <Funktionsname> = result (wobei result dein Rückgabewert/-array ist, wie auch immer dies deklariert ist. Es kann auch anders benannt werden)

@Harald:
Siemens schreibt seit TIA das komplette Script samt Aufruf und Prozedurende in den Editor. Auch können Parameter nun wahlweise als Wert oder Referenz übergeben werden, wobei lt. Siemens bei Scriptaufrufen aus einem anderen Script heraus INTERN ByRef verwendet wird, auch wenn ByVal angegeben ist!!??:???:

Gruß, Fred


----------



## RONIN (6 Januar 2015)

PN/DP schrieb:


> kennt das tatsächlich Function-Deklaration, End Function und ByRef???


Da musste ich jetzt auch nachschauen.
Die Function-Deklaration selbst passiert gleich wie bei WinCCFlex über den Eigenschaftsdialog.
WinCCFlex hat die Deklaration (FunctionName(Parameter1,Parameter2) dann in die Kopf- und Fußzeile des Texteditors geschrieben.
TIA schreibt die Deklaration direkt in den Text-Editor-Bereich. Ist aber auch nicht textlich editierbar.

Die Unterscheidung ByRef/ByVal bei der Parameter-Deklaration ist definitiv neu bei TIA.
Vielleicht kann man jetzt auch endlich Objekte zwischen Skriptfunktionen austauschen, bei Flex ging das ja nicht.

Zum Thema:
Das Skript vom TE kann ich in TIA (bis auf den fehlenden Rückgabewert) problemlos übersetzen.
Die Frage nach der Parameter-Rückgabe hat Faust ja schon erklärt.
Wenn man mehr als einen Wert von der Funktion bearbeitet haben will übergibt man diese üblicherweise ByRef, die ReturnValue kann man dann z.B. als Fehler/Status nehmen.
Insofern hat dass der TE mit "ByRef bri, ByRef hue, ByRef sat" schon richtig gemacht.

Wie genau die ByRef-Übergaben in TIA funktionieren und ob es irgendwo TIA-spezifische Begrenzungen gibt weiß ich allerdings nicht.



faust schrieb:


> wobei lt. Siemens bei Scriptaufrufen aus einem anderen Script heraus INTERN ByRef verwendet wird, auch wenn ByVal angegeben ist!!??:???:


Da hätten wir ja schon das erste Beispiel... :???:


----------



## emilio20 (6 Januar 2015)

Wie müsste die Rückgabe im Script aussehen ? Mir ist unklar wie der Array in der Variablendeklaration angelegt wird ?


```
Function HUE_Farbe_lesen(ByRef light, ByRef werte)


......Script


 werte(1)= HiField(1, 1)
 werte(2)= HiField(2, 1)
 werte(3)= HiField(3, 1)



End Function
```


----------



## holgermaik (6 Januar 2015)

Hallo emilio
Der prinzipielle Aufbau bei mehreren Werten ist folgender, wenn du kein Array verwenden möchtest:
	
	



```
Function Hue_Farbe_read(ByVal lightt (as Integer), ByRef bri (as Integer), ByRef hue (as Integer), ByRef sat (as Integer)) (as Boolean)
```
Ich kann eben nicht prüfen ob TIA die Übergabe von Deklarationen unterstütz. Darum die Klammen.
Dein Wert den du übergeben möchtest übergibtst du mit ByVal. Die Werte die du zurückerhalten möchtest übergibst du eine Referenz.
Den Rückgabewert der Funktion als Bool kannst du zur Überprüfung nutzen, ob alles ok ist.


```
Function Hue_Farbe_read(ByVal lightt (as Integer), ByRef bri (as Integer), ByRef hue (as Integer), ByRef sat (as Integer)) as Boolean
Hue_Farbe_read=false
.
.
Script
.
'alles ok
Hue_Farbe_read=true
(Return Hue_Farbe_read)
```

(Return wieder ungeprüfte Syntax)
Holger


----------



## emilio20 (6 Januar 2015)

Hallo
ich habe das Script abgeändert. Der Fehler ist weg aber ich erhalte keine Rückgabewerte. Return gibt es nicht in TIA


```
Function HUE_Farbe_lesen(ByVal lights, ByRef bri, ByRef sat, ByRef hue)

HUE_Farbe_lesen=False

Dim IP, Username
Dim result
Dim field_K, field_D
Dim i, j
Dim x
Dim Cnt1, Cnt2
Dim fso, f, ts, Path
Dim ausgabe
Dim ausgabedatei
Dim MyURL , postData 
Dim winHttpReq 
Dim HiField()
Set winHttpReq = CreateObject("WinHttp.WinHttpRequest.5.1")

i=0
j=0


IP=SmartTags("DB59 PHILIPS HUE_IP")
Username=SmartTags("DB59 PHILIPS HUE_username")

MyURL = "http://"&IP&"/api/"&Username&"/lights/"&lights&""


winHttpReq.Open "GET", MyURL, False
winHttpReq.Send 

result = winHttpReq.ResponseText


field_K = Split(result,",")            'Split nach ","

Cnt1 = 0                    'Finde Größenparameter für das Array
For i = 0 To UBound(field_K)            'Finde größte Anzahl an Substrings für ":"
    
    x = field_K(i)
    Cnt2 = Len(x) - Len(Replace(x, ":", ""))  + 1     'Anzahl der Zeichen ":" + 1
    If Cnt2 > Cnt1 Then                'Gerade "uniqueid" besteht aus vielen Teilen
        Cnt1 = Cnt2
    End If
Next

ReDim HiField(UBound(field_K),Cnt1)        'HiField neu dimensioneren

For i=0 To UBound(field_K)
    
    x = field_K(i)
    x = Replace(x, "{", "")            'Entfernen nicht gewünschter Zeichen
        x = Replace(x, "}", "")
        x = Replace(x, " ", "")

    field_D = Split(x,":")            'Split nach ":"

    For j=0    To UBound(field_D)        'Teile des Split ":" in das Array kopieren
        
        HiField(i,j) = field_D(j)
        
    Next

Next

 bri= HiField(1, 1)
 hue= HiField(2, 1)
 sat= HiField(3, 1)


 

HUE_Farbe_lesen=True

End Function
```


----------



## faust (6 Januar 2015)

Hallo emilio,

mehrere Fragen:
1. Wie sieht der Funktionsaufruf aus bzw. welchen Typ haben die Funktions-Parameter 'bri', 'sat' und 'hue?
2. Bist du sicher, dass dein internes Feld 'HiField' mit (korrekten) Werten besetzt ist?

Übrigens: meines Wissens nach kann man mit ReDim nur EINE Dimension eines Feldes verändern, nicht beide/mehrere gleichzeitig.

Gruß, Fred

PS: Schon mal versucht, die Runtime mit den Skript-Debugger zu starten? Zur Fehlersuche wirklich hilfreich.

PPS: Ich muss übrigens meine Aussage bezügl. der Siemens-spezifischen Einschränkungen etwas abmildern:
ByRef und ByVal funktionieren bei mir beim Skriptaufruf aus einem anderen Skript doch. Die Hilfe sagt aber nach wie vor etwas anderes...


----------



## emilio20 (6 Januar 2015)

Hallo
1. bri = Int , sat= Int, Hue = DInt.
2. Das Script funktioniert wenn ich eine Feste Variable verwende 


```
SmartTags("Lampe 1 bri")= HiField(1, 1)
SmartTags("Lampe 1 hue")= HiField(2, 1)
SmartTags("Lampe 1 sat")= HiField(3, 1)
```

wie geht das mit dem Runtime  Skript-Debugger ?


----------



## faust (6 Januar 2015)

Hallo emilio,

dir ist hoffentlich klar, dass du Variablentypen in einem Array/Feld nicht mischen kannst, obwohl das hier vielleicht zufälligerweise funktioniert.

Zum Problem:
Kannst du trotzdem mal den genauen Funktionsaufruf posten?

Gruß, Fred

PS: Zum Skript-Debugger siehe dje Hilfe im TIA-Portal.


----------



## emilio20 (6 Januar 2015)

Ich weiß nicht genau was du möchtest. Ich starte über einen Button das Script. Möchtest du ein Bild von der Belegung des Buttons ?


----------



## faust (6 Januar 2015)

Zum Beispiel. Interessant wäre auch, ob es beispielsweise mit internen Variablen ohne Steuerungsanbindung funktionieren würde.

Gruß, Fred


----------



## emilio20 (6 Januar 2015)

Ja mit internen Variablen geht es auch.Ich habe es in Post #16 geändert.


----------



## PN/DP (6 Januar 2015)

Hmm, könntest Du Dich nicht mal mit kleinen Schritten ins Unbekannte vortasten? Mußt Du denn immer gleich die höchst-komplizierten Skripte machen, wo Du außer dem Problem auch das meiste andere nicht verstehst? :roll:

Zum Debuggen und Beobachten von Skripten kann man Test-Ausgaben einbauen, z.B. mit ShowSystemAlarm oder in SmartTags schreiben.


Ich habe momentan kein TIA zur Verfügung, doch wenn, dann würde ich zunächst etwas einfaches ausprobieren. Etwa sowas (alles nicht getestet):

```
Function Test_function(ByRef light, ByRef bri, ByRef hue, ByRef sat)

Test_function = light  'Rückgabewert der Function

light = 11             'Rückgabe über Aufrufparameter
bri = 12
hue = 13
sat = 14

End Function
```

Dazu das Aufruf-Skript:

```
Dim wert1, wert2, wert3, wert4, result

wert1 = 1
wert2 = 2
wert3 = 3
wert4 = 4

result = Test_function(wert1, wert2, wert3, wert4)

ShowSystemAlarm "Result: " & result & " Wert1: " & wert1   '...


'geht das auch mit SmartTags?
'result = Test_function(wert1, SmartTags("Lampe 1 bri"), SmartTags("Lampe 1 hue"), SmartTags("Lampe 1 sat"))
```

Erst wenn das funktioniert, dann lohnt es sich, die Rückgabe von Werten aus einem Array zu versuchen. Und dann mal als Übergabeparameter direkt SmartTags anzugeben.




emilio20 schrieb:


> ich möchte gerne 1 wert in die Funktion übergeben und 3 werte aus dem Script zurückgeben. Leider Funktioniert dies nicht. Ich habe gelesen das ich hierfür eine Funktion verwenden muss keinen Sub.


Wo hast Du das gelesen bzw. was steht da genau?
Warum das Werte zurückgeben über ByRef-Aufrufparameter nur in einer Function funktionieren soll erschließt sich mir nicht.

Harald


----------



## hucki (7 Januar 2015)

PN/DP schrieb:


> Hmm, könntest Du Dich nicht mal mit kleinen Schritten ins Unbekannte vortasten? Mußt Du denn immer gleich die höchst-komplizierten Skripte machen, wo Du außer dem Problem auch das meiste andere nicht verstehst? :roll:


*ACK*

Das denk' ich mir nicht nur bei emilio20.


----------



## emilio20 (7 Januar 2015)

Hallo
folgende Ergebnisse habe ich


```
Sub VBFunktion_1()
Dim wert1, wert2, wert3, wert4, result

wert1 = 1
wert2 = 2
wert3 = 3
wert4 = 4


result = Hue_Farbe_read(wert1, wert2, wert3,wert4)

'Funktioniert
ShowSystemAlarm "Result: " & result & " Wert1: " & wert1 & " Wert2: " & wert2 & " Wert3: " & wert3 & " Wert4: " & wert4  '...

'Funktioniert nicht
result = Hue_Farbe_read(wert1, SmartTags("Lampe 1 bri"), SmartTags("Lampe 1 sat"), SmartTags("Lampe 1 hue"))

End Sub
```


```
Sub VBFunktion_1()
Dim wert1, wert2, wert3, wert4, result

wert1 = 1
wert2 = 2
wert3 = 3
wert4 = 4

result = Hue_Farbe_read(wert1, wert2, wert3,wert4)

'Funktioniert
ShowSystemAlarm "Result: " & result & " Wert1: " & wert1 & " Wert2: " & wert2 & " Wert3: " & wert3 & " Wert4: " & wert4  '...

'Funktioniert
SmartTags("bri")=wert2
SmartTags("sat")=wert3
SmartTags("hue")=wert4


End Sub
```


----------



## MrFisch (13 September 2016)

Hi Emilio,

ich verfolge momentan deine Hue Programmierung in den Foren. Momentan bin ich auf das selbe Problem gestoßen, dass du wohl auch hattest. 

Ich bekomme immer die Fehlermeldung mit "Fehler ActiveX component cant create object: winhttp.winhttprequest.5.1 in Skript. 

Wie hast Du das gelöst? Würde mich über eine Antwort sehr freuen. 
Vielen lieben Dank
Michi


----------



## emilio20 (13 September 2016)

Hallo das Skript Funktioniert nur auf einen Windows XP, 7, 10 Bediengerät da nur diese  ActiveX winhttp unterstützen.
Auf einen Win CE Bediengerät geht dies nicht. 

Am besten einen IPC mit Win 7 verwenden.


----------

