Loop through each row in dynamic column using Excel Tables and VBA - vba

I am trying to loop through various elements in a Vertical Excel Table and pass them to a horizontal table using VBA. The vertical table is a form that contains a list of questions (name,label,value) and the horizontal table will contain columns using the question name from the vertical table.
The code looks something like this:
Dim row As Range
Dim rowCount As Integer: rowCount = 1
For Each row In [tbl_QUESTIONS[name]].Rows
Sheets(ANSWERS).Cells(r,rowCount).Value = row.Value
rowCount = rowCount + 1
Next
My question is, how can modify the table reference and column reference so that they are dynamic?
[tbl_QUESTIONS[name]].Rows
I would like to be able to do something like this:
["tbl_" & tblName & "[" & colName & "]]".Rows
But that doesn't seem to work... Is there a simpler way to reference this using VBA? I get the feeling that there has to be a way of creating the ListObject out of ["tbl_" & tblName] but I haven't been able to reference 'colName' inside the ListObject or the ListObject.Rows
Any help would be appreciated.
Oh, and I'd like to keep this compatible with Excel 2007 VBA if at all possible.
Cheers!

I've stumbled upon this link and it seems to do the trick.
Looks like I can create a range using the following:
Dim TBL As Range
Set TBL = Range("tbl_" & tblName & "[" & colName & "]")
I'd still like to see a way of keeping the ListObject rather than defining a range, but I'll go with this until I have an alternative.

You probably know this by now but since the question has no answer...
use the LisObjects collection to select a listObject and pass that as a parameter to your function/sub

Related

How to use a word table as mailmerge datasource

I have a word document containing a table I need to use as mailmerge datasouce.
I've reached my goal by copying data of the word table to excel and using the sheet as datasource.
Now my question is: is there a way to use the word table as datasource (I mean create a datasource using the data in the word table) without calling excel?
I'm asking this because I need to use a word-vba macro and I'm trying to avoid opening an excel instance.
edit
I'll try to clarify what I'm looking for with the following pseudocode (I added a "What for this?" in wrong code lines):
Dim mDoc As Document
Dim mTbl As Table
Set mDoc = ActiveDocument
Set mTbl = mDoc.Tables(1)
Dim mDS As MailMerge.DataSource 'What for this?
For C = 1 To mTbl.Columns.Count
'Add Fields
Dim FieldName As String
FieldName = mTbl.Cell(1, C).Range.Text
mDS.Fields.Add (FieldName) 'What for this?
'Add Values
For R = 2 To mTbl.Rows.Count
mDS.Fields(FieldName)(R) = mTbl.Cell(R, C).Range.Text 'What for this?
Next R
Next C
In Word, start with a blank document, then add one table. Enter the category in the top row (i.e. First Name, Last Name, etc). Then add the data in the rows below. Then you should be able to use a statement like this to connect:
ActiveDocument.MailMerge.OpenDataSource Name:="Y:\Test\Word\MailmergeSource.docx", LinkToSource:=True, SubType:=wdMergeSubTypeOther

VBA script to insert INDEX/MATCH formula with dynamic reference/arrays

I'm looking to simply insert an INDEX/MATCH formula in the column next to an existing selection (this will be part of a larger Sub). The reference/look-up array in the formula needs to be dynamic.
So far I've managed to successfully insert the formula. However, the reference/lookup-arrays have been manually input by me as I know the current Range (which is likely to change):
Selection.Offset(0, 1) = "=INDEX($J$3:$J$31,MATCH(INDIRECT(""RC[-2]"",0),$H$3:$H$31,0))"
How can I amend the $J$3:$J$31 and the $H$3:$H$31 to update dynamically? I've had success separately with something like 'Range("J3", Range("J3").End(xlDown))', but I can't seem to work it into the code above.
You can integrate variables into the formula, it becomes a bit tricky, and I imagine there are better ways to accomplish this, but it's the method I use when I need dynamic ranges in formulas in VBA. I'll provide an example below that should help:
I'm assuming the J3 and H3 will remain the same, but the end of the range is what you expect to change. If this is not the case, let me know.
You're essentially replacing the "31" in your range reference with " & [variable] & " (quotes included).
EDIT: I use Sheet1 as an example for the row count; so just update that to whatever the applicable sheet & range would be.
Dim rCount As Long
rCount = Sheet1.Range("A" & Rows.Count).End(xlUp).Row
Selection.Offset(0, 1) = "=INDEX($J$3:$J$" & rCount & ",MATCH(INDIRECT(""RC[-2]"",0),$H$3:$H$" & rCount & ",0))"

Returning a quick statistical info for a cell as a comment

I have a long list of data on an excel table. This data includes detail information of each order in several rows. There is a column shows the status of each row. Also, I have a dashboard which just lists out the order names. I want the users to be able to see a short statistical info of each book as a comment or when they mouse over the cell, if possible or as a cell data. The info could be something like underneath sample in 3 or 4 row. (The number of items is the count of rows with the same status)
5 issued item
3 shortage items
2 Done items
X other
If you just give me the general idea it would be great.
I think I have to use a collection procedure, something like "scripting dictionary" but I have no experience using them. I know how to do that by putting a case statement after if clause inside a loop, but I am looking for a smarter way. you can find some pictures and a sample data below: sample pictures
For the record, I came to this answer from one of friends in MrExcel froum. Hope you find it usefull.
The just difference is, I was looking for a momentum reply just for an active cell, but this code, provide all the information for all the order names as a comment. but it is very easy to adjust!
Sub UpdateComments()
Dim c As Variant, strComment As String
Dim intISSUED As Integer, intSHORTAGE As Integer
Dim tblDATA As ListObject, tblDASH As ListObject
Set tblDATA = Application.Range("TBL.data").ListObject 'adjust Table Name
Set tblDASH = Application.Range("TBL.dash").ListObject 'adjust Table Name
For Each c In tblDASH.ListColumns("W/B").DataBodyRange
strComment = ""
intISSUED = Application.CountIfs(tblDATA.ListColumns("Work Book").DataBodyRange, c, tblDATA.ListColumns("Stage").DataBodyRange, "Issued")
strComment = strComment & Chr(10) & "Issued: " & intISSUED
intSHORTAGE = Application.CountIfs(tblDATA.ListColumns("Work Book").DataBodyRange, c,tblDATA.ListColumns("Stage").DataBodyRange, "Shortage")
strComment = strComment & Chr(10) & "Shortage: " & intSHORTAGE
' ADDITIONAL 'STAGES' HERE
' OR put 'stages' in array to condense code
With Sheets(tblDASH.Parent.Name).Range(c.Address)
If .Comment Is Nothing Then
.AddComment
.Comment.Visible = False
End If
.Comment.Text Text:=Mid(strComment, 2)
End With
Next c
End Sub

Excel VBA: Copy the Data up to the last column that has value

The spreadsheet has multiple values in a cell.
What I'm trying to do is get that value found in a cell and paste it to another sheet and copy the other fields(columns) that belong to that value. How do I set the range in order copy the other fields(columns) up to the last column that has value? Thanks in advance.
For iRowGetProdCode = 0 To UBound(sSplitProdCode)
Sheets("Output").Cells(iRowCountOutput, 1).Value = sSplitProdCode(iRowGetProdCode)
iRowCountOutput = iRowCountOutput + 1
Next iRowGetProdCode
here is an idea how to discover an un-empty columns in the same row,
maybe you will find it useful and manipulate it for your needs:
Function LoopUntilLastColumn(ByVal Row As Integer)
Dim i As Integer
i = 1
Do While Cells(Row, i) <> ""
' do somthing
MsgBox (" I AM ALIVE COLUMN!")
i = i + 1
Loop
' you can also use the return value of the function.
LoopUntilLastColumn = i
End Function
I'm not exactly sure about what you're asking, but here are my three best guesses.
1.) Splitting delimited data from a single cell to columns
Without VBA: Use the "Text to Columns" function (Excel Ribbon:
Data|Data Tools).
With VBA: Use the split function MSDN (Related Post), then assign array values to target cells. Or parse your string manually with a loop.
2.) Finding the end of a continuous range
Without VBA: Use ctrl + arrow key
With VBA: Use the Range.End Property
3.) Looping through columns and rows
Used a nested loop:
For c = 1 to 5
For r = 1 to 20
Cells(r,c) = "Row = " & r & ", Column = " & C
Next
Next
Editing Suggestions (I don't have enough reputation to directly comment or edit)
This question as worded may be too specific for StackOverflow. Consider re-wording so that the problem can be understood in a general context and your question can be more useful to others.
Also, the wording is a little confusing. For example, use of the term "value" seems to change from referring to delimited data to referring to cell content in VBA. Likewise, it can be confusing to use "fields" or "columns" to describe the data if it's actually delimited text, so clarity on the data's state of existence would help.
It also seems to me that you've parsed the string on it's delimiter to an array, and that you're looping through this array to write the data in rows. I still can't see how exactly your question about setting a range fits in.

How do I use the [[#Headers],[Column]] notation with a table ListObject instead of a "TableName"?

I am trying to convert a recorded macro to a generic VBA script (my first one ever). The recorded macro produced specific names in the code like Sheet8 and Table5. I need these to be determined dynamically in the code, and so far, I've been able to figure that out...
'This table name needs to be dynamically determined...
Dim myTable As ListObject
Set myTable = ActiveSheet.ListObjects.Add(xlSrcRange, myRng, , xlNo)
However I need help figuring out how to convert these lines...
Range("Table5[[#Headers],[Column1]]").Select
...to something that uses the myTable ListObject.
Any ideas? Thanks!
Try this one:
Dim myTable As ListObject
Dim myRng As Range, rngH1 As Range
'where to place the table
Set myRng = ThisWorkbook.Worksheets("Sheet1").Range("D5:H10")
'create table
Set myTable = ActiveSheet.ListObjects.Add(xlSrcRange, myRng, , xlNo)
'get firts header
Set rngH1 = myTable.HeaderRowRange.Columns(1)
'select first header (assuming that Sheet where table placed is active)
rngH1.Select
If you want to find header using it's name, you can do:
'select header "Column3" (assuming that Sheet where table placed is active)
myTable.ListColumns("Column3").Range(1).Select
also may be interesting: how to avoid using Select/Active statements