ReDim on custom type containing dynamic array

Hi all!

I have received an Excel sheet containing a VBA macro and it gives an error about using ReDim. So to narrow the problem down I have created a simple script that shows the error.

Option VBASupport 1

Type MyTyp
    a() as String
End Type

Sub Main
    Dim typ as New MyTyp
    ReDim typ.a(0)
    typ.a(0) = "Hello"
    Print(typ.a(0))
End Sub

When I run this script I get the following error: BASIC syntax error. Expected: ,. for the line containing ReDim.
If I replace the b.a(0) part with the suggested b,a(0) (notice the change from the dot to a comma) then ReDim does nothing and I get an out of index error.

The Excel sheet actually contains a variation of the above:

Sub Main
    Dim typ as New MyTyp
    With typ
        ReDim .a(0)
        .a(0) = "Hello"
    End With
    Print(typ.a(0))
End Sub

And that gives me the error: BASIC syntax error. Symbol expected. at the line with the ReDim.

I have noticed that if I do this, then it works:

Sub Main
    Dim a() as String
    ReDim a(0) as String
    a(0) = "Hello"
    Print(a(0))
End Sub

So it seems that I cannot use ReDim with a custom type. Is there any way I can still do this? It would seem silly if ReDim does not work on dynamic arrays in custom types.
I could replace the ReDim xxx(0) with xxx = DimArray(0) but I also have statements with Preserve in it and I don’t know how to fix that.

Thanks for your time!

My sixth sense says that this usage is just outside of BASIC canon. Even if one got it to work, it would be something of a show pony. Might I recommend just using variable nomenclature rather than user types? Is there a functional need for types here?
.
One could also use a proper class. It would be more interesting if something didn’t ReDim properly in a class module. (BTW, there are bugs with ReDim in conditional structures–or were until recently). LO BASIC differs from VBA in class modules just a little bit. See Option ClassModule.
.
That said, “no one” uses classes in LO BASIC, just like “no one” uses types.

It is simply used as a struct to group related variables, just like pretty much any programming language invented in the last 50 years :wink: I cannot imagine why the language would support user types but make it cumbersome to use. Personally, I would have written a Python program that reads the contents of the sheet so that it is portable, but I’m not the author of the sheet.

If anything works with VBA, but fails with LibreOffice’s Option VBASupport, it’s a bug, and should be reported to have a chance to be fixed at some point.

I don’t know if it makes sense to log this as a separate bug. The problem described may well be part of that condemnation.

Thanks for the remainder! :slight_smile:

Still, each specific problem should have a separate bug. Developers may decide that several of them are a single issue - but that’s up to the developer who fixes that. Otherwise, having several issues makes it possible to check separately if some fix had fixed different problems, or if some persist.

By the way, the problem here looks like it’s a problem of compiler (syntax parser), which doesn’t expect a member syntax, so it is before the byref handling problem even appears… Please do file a bug report.

I just filed a bug report: https://bugs.documentfoundation.org/show_bug.cgi?id=149489

1 Like

Welcome!
Think of variable of a user-defined type as a structure. You can get any part of it any time to use. But (in most cases) you cannot change part of a structure directly. Copy the mutable part into a variable, change it, and put it back.


Option Explicit 
Type MyTyp
    a() as String
End Type

Sub Main
Dim typ as New MyTyp
Dim aTemp() As String 
	aTemp = typ.a
	ReDim aTemp(0)
	aTemp(0) = "Hello"
	typ.a = aTemp
	Print(typ.a(0))
' Want re-dim part? Copy, change and and put it back:
	aTemp = typ.a
	ReDim Preserve aTemp(2)
	aTemp(1) = "World"
	aTemp(2) = "!"
	
	typ.a = aTemp
	Print(Join(typ.a))
End Sub
1 Like

Ah so that’s why my code didn’t work. Programming language wise I don’t know why this shouldn’t be possible, but I couldn’t find any resource that explains this, so thank you very much! :slight_smile:

To be honest, I don’t know either. Something related to dynamic memory allocation, passing objects by reference, something very boring and incomprehensible … Just accept it “as is” and use it in the future

At first I thought, “Of course, structs here are just like using UNO structs, @JohnSUN is on the money.” Then I tried with a simple class and got the same result. That made me suspicious. I checked, and so far as I can tell, it’s just a bug in ReDim parsing. Consider this rewrite of JohnSUN’s code:

Sub Main
	Dim typ as New MyTyp
	Dim aTemp() As String 

		aTemp = typ.a
		ReDim aTemp(0)
		typ.a = aTemp

		typ.a(0) = "Hello"
		Print(typ.a(0))

	Rem Want re-dim part? Copy, change and and put it back:

		aTemp = typ.a
		ReDim Preserve aTemp(2)
		typ.a = aTemp

		typ.a(1) = "World"
		typ.a(2) = "!"		
		Print(Join(typ.a))
End Sub

This works perfectly. The problem isn’t with referencing members of the struct, it’s just that the ReDim statement doesn’t do what it says. ReDim Statement says that ReDim can be followed by “Any variable or array name.” But in fact it can only be followed by any “simple” variable or array name. Just by feeding ReDim a simple name using JohnSUN’s reassignment trick, one avoids the ReDim failure to parse, and all is good. A person can still assign directly to BASIC struct members using structure syntax (the dot). [Caveat with UNO structs…I’m not sorting out the details here on this.]

BTW, I tried putting ReDim in a With block…no luck, as one might guess.

Long and short of it is just wrap the ReDim with a simple variable name temp, and it’s done.

1 Like