Home » excel » perl – Excel VBA – How to create AND dump hash of arrays complex structure?

perl – Excel VBA – How to create AND dump hash of arrays complex structure?

Posted by: admin April 23, 2020 Leave a comment

Questions:

I am from perl background and learning Excel-VBA. In perl, we can use Data::Dumper to get the dump of data structure.

Here is the example from perl:

use strict;
use Data::Dumper;

my $hash={};
$hash->{key1} = [ 1, "b", "c" ]; # the value stored against key1 here is an array
$hash->{key2} = [ 4.56, "g", "2008-12-16 19:10 -08:00" ]; # the value stored against key2 here is an array
my $hash2={1=>['one','ONE']}; # this is a hash
$hash->{key3}=$hash2; # the value stored against key3 here is a hash

print Dumper($hash)."\n";

It produces following output:

$VAR1 = {
         'key2' => [
                     '4.56',
                     'g',
                     '2008-12-16 19:10 -08:00'
                   ],
         'key1' => [
                     1,
                     'b',
                     'c'
                   ],
         'key3' => {
                     '1' => [
                              'one',
                              'ONE'
                            ]
                   }
        };

As I mentioned earlier, I am new to Excel-VBA and learning it so please bear with me in helping me reach to the answers of below questions:

  1. Is there something similar to perl’s Data::Dumper in Excel-VBA?
  2. How do I create a structure exactly similar to above (i.e. $hash) in Excel-VBA using Scripting.Dictionary object? How do I iterate over that structure and retrieve a value stored against the key? Does this kind of structure support ‘exists’, ‘remove’, ‘add’ etc etc methods?
How to&Answers:

I am not aware of a built in mechanism that will do what you are asking. You would have to create a “keyedArray” class which implements the methods that you want. Figuring that out would put you solidly up the VBA learning curve.

A good place to start would be http://www.cpearson.com/excel/classes.aspx

If that doesn’t help you, say so in the comments – I may have some time later to put a brief example together.

Answer:

You may have one of three needs:

  1. Interactive Debug – then add a breakpoint in the debugger, use the Add Watch in vba, and expand the structure iteractively
  2. Get the data to a text file for some post treatment -try to look for xml or json exporter
  3. Get the data exactly as you show, to import e.g. with Safe into Perl. – then you need to write a recursive procedure yourself.

The latter will be quite difficult, as most vba-structures (unless you make them yourself), have cylcles. (like children => [ … ], parent => FIX).

VBA Collections does not give you enough support so Dictionary is what you need. (remember to Tools->References to “Miscrosoft Scripting Runtime”)

The following is not pefect, but may give you a start

Option Explicit ' aka use strict
Option Base 0 ' to be close to perl

Sub test()
    Dim c As New Dictionary
    Dim c2 As New Dictionary
    Dim a(10) As Variant, b() As Variant
    a(1) = 1.1
    a(2) = "array item 1"

    ReDim b(0)
    b(0) = 41.9
    ReDim Preserve b(UBound(b) + 1) ' aka push
    b(UBound(b)) = 41.95

    ReDim Preserve b(UBound(b) + 1)
    b(UBound(b)) = 41.96

    '#build a structure
    c.Add item:="val1.2", Key:="key1.2"
    c.Add item:="val1.1", Key:="key1"
    c2.Add item:="val2.1", Key:="key2.1"
    c2.Add item:=42, Key:="key2.2"
    c2.Add item:=42.1, Key:="key2.3"
    c2.Add item:=a, Key:="key2.4"
    c2.Add item:=b, Key:="key2.5"

    'add c2 to c to make it hierarchical
    c.Add item:=c2, Key:="key1.3"""

    Debug.Print vba2perl(c)

End Sub

Function vba2perl(item, Optional indent = 0)
    Dim txt
    Dim Key, I

    Select Case TypeName(item)

    Case "Dictionary"
        indent = indent + 1
        txt = txt _
            & vbCrLf & Space(indent * 4 - 2) & "{"
        For Each Key In item
            txt = txt _
                & vbCrLf & Space(indent * 4) & Key & " => " & vba2perl(item(Key), indent) & ","
        Next Key
        txt = txt _
            & vbCrLf & Space(indent * 4 - 2) & "}"
    Case "String"
            txt = item
            txt = Replace(txt, """", "\""") ' more escaping needed
            txt = """" & txt & """"
    Case "Integer"
            txt = item
    Case "Double"
            txt = item
            txt = Replace(txt, ",", ".") ' if regional, then fix . vs , tbd
    Case "Empty"
            txt = "undef"
    Case "Variant()"
        indent = indent + 1
        txt = txt _
            & vbCrLf & Space(indent * 4 - 2) & "["

        For I = LBound(item) To UBound(item)
            txt = txt _
                & vbCrLf & Space(indent * 4) & vba2perl(item(I)) & ","
        Next I
        txt = txt _
            & vbCrLf & Space(indent * 4 - 2) & "]"
    Case Else
        Debug.Print "No Handler for type: " & TypeName(item)
    End Select

    vba2perl = txt
End Function