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 function
Ei 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 Function
Olen 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 Function
Onpa 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 Sub
Ja 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 Sub
Mahtavaa. 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.