Hei. Olen keskinkertainen koodarinalku, joka haluaa ratkoa kaikenlaista työkamaa lähinnä vba:n ja autocadin avulla. Erääseen ongelmaan olen törmännyt jota en osaa ratkaista, nimittäin olio-arvoisen taulukon palauttamista funktiosta. Myöskään en ole löytänyt mistään valmista ratkaisua. Seuraavanlainen "pseudo-koodi" ei ainakaan toimi. Tietääköhän joku, onko dynaamisen kokoista object-arrayta edes mahdollista palauttaa funktiosta?
Ei toimi:
Dim oliot() As Object
Set oliot() = palautaOliot("parametrejä")
Function palautaOliot(parametreja As String) As Object()
for i=0 To 3
palautaOliot(i) = New Object
next i
end functionEi tietenkään toimi, mutta voisiko toimia variant-tyyppisellä palautusarvona, siis jos funktion määrittelyssä olisi As Object():n tilalla As Variant?
Mod. lisäsi kooditagit
Toimii. Äkkiähän olisit itsekin sen testannut.
Ehkä en ole aivan perillä näistä visual basicin versioista. Käytössäni on vba joka toimii autocad 2010 sisällä. Edellä oleva koodi ei mielestäni toimi siinä. Ainoa toimiva tapa mielestäni on VBA:ssa tehdä kaikki liittyvät muuttujat variant-tyyppisiksi, alla olevan koodin mukaisesti. (Toimiva ratkaisu, muttei kovin elegantti)
Sub olionPalautus()
Dim oliot As Variant
oliot = palautaOliot("parametrejä")
End Sub
Function palautaOliot(parametreja As String) As Variant
Dim k As Integer
Dim olioita(0 To 2) As Variant
For k = 0 To 2
olioita(k) = New excel.Application
Next k
palautaOliot = olioita
End FunctionOlen käsittänyt, että hyvä ohjelmoija ei käytä variant-tietotyyppiä juurikaan. Sen käyttäminen on kuitenkin VBA:ssa näköjään varsin tarpeellista. Tietääkö kukaan, onko tämä olioiden toiminta sitten jotenkin "parempaa" jossain muussa visual basic-ympäristössä?
Minulla kyllä toimii tuo koodisi suoraan VBA:ssa joka sisältyy uusimpaan Exceliin (VBA 6.5.1040)
Ainakin VB.Netillä onnistuu Object-taulukon palautus suoraan. VBA:ssakin onnistuisi jos se ymmärtäisi syntaksin oikein.
No, jos minä ajan alla olevan koodin (VBA 6.5.1024), tulee virheilmoitus, "Compile error: can't assign to array"
Sub oliot()
Dim oliot() As Object
Set oliot() = palautaOliot("parametrejä")
End Sub
Function palautaOliot(parametreja As String) As Object()
For i = 0 To 3
palautaOliot(i) = New Excel.Application
Next i
End FunctionOnpa outoa, että toisilla toimii, toisilla ei. Toisaalta visual basicin tyyppipakotus ei toimi myöskään vba:ssa, joten en ihmettelisi vaikka muutenkaan ei oikein toimi. Esim. jos oliot taulukko on variant-tyyppinen, VBA:ssa siitä ei saa myöhemmin pakotettua object-tyyppistä.. Vai saako jotenkin kikkailemalla?
No sama virhe minullakin tulee tuosta, mutta ei se ole sama koodi kuin edellisessä viestissäsi.
Tuo Can't assign to array ei liity mitenkään siihen, mitä funktio palauttaa, vaan ainoastaan siihen että et voi sijoittaa taulukkoa toiseen taulukkoon tuolla tavalla. Avain sama vaikka olisit tehnyt sen funktion palauttaman taulukon paikallisesti.
Sitten tuosta palautaOliot funktiosta tulisi myös virheilmoitus "Function call on left-hand side of assignment must return variant or Object" ja tämä johtuu tuosta mitä sanoin, että VBA ei ymmärrä tuossa tapauksessa kirjoittamaasi syntaksia oikein (siis niinkuin olet sen tarkoittanut) vaan tulkitsee palautaOliot(i) kohdassa että funktio kutsuisi itseään.
Itse asiassa, saahan tuon palauttamaan objektitaulukon kun vähän käskee.
Function palautaOliot(parametreja As String) As Object()
ReDim palautaOliot(3)
Dim i As Long
For i = 0 To 3
PutInObjectArray palautaOliot, i, New Excel.Application
Next i
End Function
Private Sub PutInObjectArray(ObjectArray() As Object, Index As Long, MyObject As Object)
Set ObjectArray(Index) = MyObject
End SubJa tästä päästäänkin sitten siihen, että olisi paljon helpompaa vaan antaa se taulukko parametrina kutsuvasta funktiosta.
Sub Oliot()
Dim res As Variant
Dim Oliot() As Object
palautaOliot "parametrejä", Oliot
End Sub
Sub palautaOliot(parametreja As String, Oliot() As Object)
ReDim Oliot(3)
Dim i As Long
For i = 0 To 3
Set Oliot(i) = New Excel.Application
Next i
End SubMahtavaa. Kiitos! En ole ennen uskaltautunut kyselemään tällaisia pieniä koodijuttuja, mutta täytyy sanoa että kyllä olis kannattanut, eikä hakata päätä seinään.
Aihe on jo aika vanha, joten et voi enää vastata siihen.