Excel is just a grid, so you could use a multi-dimensional array.
My tests are all keyword and data driven from Excel. but I don't read the entire Excel sheet in. I go one row at a time and store a pointer for the current position in the worksheet.
For me, each "row" is a test. Each spreadsheet is a test "pack". A full "suite" can consist of many "packs". And, obviously, a pack can contain many "rows".
Each row contains:
Run Flag (required - y or n) / Timestamp (blank - filled in when it runs) / Pass or Fail (blank - filled in when it runs) / Function Name (required) / One or more Input Parameters (optional) / One or more expected results. (optional)
So, a row is read. If the row is to be run, it reads in the function name, and any input parameters. It then builds that into an executable string (it adds brackets, commas, double/single quotes where required ... etc). This is then run using the "Eval" command. This is all wrapped in error handling so the user can't break it with bad data. Expected results are read in separately within the function that is then called. But the excel pointer is still in the same place (it does not increment until the current test had completed/finished/failed) so it always gets the right data. On completion (or failure - whatever really), the row is updated with a timestamp and the appropriate result, and it moves on. It saves after each row, so even if the machine gets unplugged halfway through, you'll still have all results and logs up to that point.
I do this through my own scripted framework. The DDT driver was a bit too limiting for me. It's done as script extensions so all commands into and out of the input sheets (and logs - I use my own for those too) is integrated into the IDE.