Please have a look at this table, which I have named "Tasks":
It is a very basic GANTT chart-like table. Using VBA I use data from this table in order to perform some tasks in other Worksheets.
I have a For loop which loops through each row like this:
For i = 1 To Range("Tasks").Rows.Count
Worksheets("Calendar").Cells(i,2).Value = Range("Tasks").Cells(i,2)
End For
There are many other operations within the For loop, but that goes beyond the scope of my question. Basically what this does is that it loops through the entire table and performs various operations and calculations (where applicable) which results in populating other cells in other worksheets.
My question is this:
Since all columns in the table are labeled, I would like to somehow reference the Column name instead of column number in the loop, if it is possible of course.
For example:
Worksheets("Calendar").Cells(i, 2).Value = Range("Tasks").Cells(i, "Title")
This helps for code readability since then I would know that this references the "Title" column, instead of going back and forth to see which column is e.g. the number "2".
I know that this kind of reference can be done in Excel by using
=Tasks[Title]
(e.g. This expression can be used for Data Validation)
Is it possible to reference columns like this? I am relatevely new to VBA, so I'm not quite sure.
Looking forward for your answer.
if it's an Excel Table, then you can use
Dim lo As ListObject
Dim col As ListColumn
Dim r As Range
Set lo = ActiveSheet.ListObjects("Tasks")
Set col = lo.ListColumns.Item("Title")
r = col.DataBodyRange
For i = 1 To Range("Tasks").Rows.Count
Worksheets("Calendar").Cells(i,2).Value = r.Cells(i)
End For
Related
I have 6 different tables Week(x) where x = a cell reference from a central run page.
Once the run button is hit I have code that clears the previous sheet and then stores the relevant week table as an array before putting those array values into the new table. Code works fine the values from the table input into the new table correctly. My question is it possible to store the Interior color of the cells in the table? I did try using RGB(x,y,z) however I believe these values need to be a constant.
I know I could just f loop into a separate array without making use of the listobject, but I'm just wondering if there's a neater way of doing it using the list object created/table.
lnWeek = Cells(5, 3)
lnTable = "" & "Week" & lnWeek & ""
Set tbl = ActiveSheet.ListObjects(lnTable)
laArray = tbl.DataBodyRange
For x = LBound(laArray) To UBound(laArray)
laArrayCol(x) = tbl.Range.Rows(x).Interior.Color
Next x
Where laArray = list of names in the table _
laArrayCol = should store the interior color
Range.Rows(x).Interior.Color doesn't work, could I store the color of the cell in a two dimensional array along with the name of the cell or am I better off having two arrays?
Sorry if I've rambled a bit.
Summary
What options do you have in storing the interior color of a cell from a dynamic table?
Any help would be appreciated, sure I've made it more difficult than it has to be.
Edit: I know I could copy and paste as that would take the formatting along with it, but trying to avoid that if possible.
I would like to find the text "Currency" in columns A or B, store all the currencies listed under Currency. Same process for Amount (Can be in an column)
Store values in an array. Then paste in Output Sheet. The currencies will already be listed in Output sheet in 1st row of the sheet. However if it is a new currency then the code should find last used cell in row 1 and add it. The value of Amount should be added to Output sheet against the currency and ID number also copied from the Source sheet.
I have some code.
Public Sub loopRow()
Dim curArray As Variant
Dim listarray As Variant
Dim cnt As Long
'Find Currency
Dim rgFound As Range
Set rgFound = Range("A:B").Find("Currency")
'Find last used row
curArray = Cells(rgFound.Address).End(xlUp).Row
'Transpose list of currecny from the row down from the word Currency that it has found
listarray = Application.Transpose(Cells(Rows, curArray).End(xlUp)).Row
For cnt = LBound(curArray) To UBound(curArray)
curArray(cnt) = curArray(cnt)
Next cnt
For cnt = LBound(curArray) To UBound(curArray)
'Debug.Print curArray(cnt)
'Copy and paste into Sheet under the correct curreny, if new currency then add this in row A
Next cnt
End Sub
Whilst you need to understand your question is unanswerable as is, I'll do my best to help.
The problem we have is not seeing the source sheet the way you do, as we can't see it at all. You say you have the word Currency in columns A or B or both, and an ID column somewhere, and Amount values everywhere. That's tricky source data. If as is more likely, the ID is in a specific column and the amounts are in a set of columns, then we'd have a chance.
Your question outlines the basic steps you'd want to take pretty well, so you're off to a good start.
However you can do all of the work without VBA, certainly if I'm right about the Source data. Create yourself a working sheet, or multiple working sheets. Definitely one to sort out the full list of currencies. Grab a copy of columns A and B (by formulae) and then have the working sheet go through line by line and use logic to build the list. Spreadsheets are great at this.
Once you have the list, use it as row headers on your Output sheet and use sumifs to get the values. I am not sure how the IDs would fit in, but if they were to be your row headings, then do the same as the above to get the list of unique ids and link them into your Output page in column A. Your sumifs can handle that.
That will hardly tell you all you need to know, but if you work it out you'll have learned a lot about Excel and when you need to go into VBA.
If you'd rather do it with VBA, break down each step until it works, and then go onto the next one.
And if you want more help, paste your data in here. Anonymise it first if you need to.
I have a worksheet of athletes whose names appear all in one row. I want to grab all of the data underneath these names (aka the whole columns) so that I can manipulate the data. My issue is that I'm not familiar with available methods or functions in Excel VBA so I have only gone as far as this:
Dim MyArray(0 to 9) as String
MyArray(0) = "Molly"
MyArray(1) = "Jane"
MyArray(2) = "Louis"
MyArray(3) = "Omar"
MyArray(4) = "Wendy"
MyArray(5) = "Greg"
MyArray(6) = "Tina"
MyArray(7) = "Andrew"
MyArray(8) = "Jen"
MyArray(9) = "Lucy"
I'm thinking of creating a script that will look through all the names and select the columns whose names match the values in the Array.
EDIT: I've uploaded an example WS here for reference (please forgive me if this is not according to SO standards, still trying to figure out how this site works and I don't have enough rep to post images :D). I'm interested in manipulating the numbers in the "Total" row, and need to showcase it (along with the specific names that it belongs to). I want to iterate this manipulation over all instances that these names pop up in the WS though, so a loop of sorts would be necessary
Thanks again for the tips/help!
You can loop accross the columns. The code below assumes the columns & your array are in the same order and that you are interested in the first 10 rows of each column of sheet 1.
With Worksheets (1)
For x = 1 to (UBound (MyArray) +1)
' Select column
Range (.Cells (1, x), .Cells (10, x)).Select
' Do whatever you want with the data
'
Next x
End With
You can make this more intelligent using If statements to check whether the first cell in each column matches a name etc. but at least it's a start!
Has anyone come across a situation where Excel seems to manipulate your formulas.
I have a sheet where I have an Index value in Column A. The First row starts with any non zero Value. Subsequent rows in the column increment the value. Eg
A1 = 1000
A2= A1+ 1
A3= A2 + 1
and so on/
I have another column B whose values will either be blank or a formula pointing to column A(usually the subsequent rows)
Eg:
B1.Formula = "=A2"
B2.Formula = "=A3"
B3.Value = ""
B4.value = "=A6"
Now I have a backup-restore functionality that lets me write out the data/formulas to a text file and then read it back in another workbook.
In the case of columns A and B, I am checking if the text value starts with "=" and then set either the value or formula of that cell depending on whether there is a formula or not.
So far the functionality has worked fine. It lets me restore accurately.
Now, if I convert this data range to a table and modify the code accordingly the behaviour is strange. I am using the ListObject structure to refer to the table. So for Column B my restore code is:
If Left(soureString) = "=" Then
'This is a formula
Sheets("MySheet").ListObjects(1).ListColumns("Next").DataBodyRange(row).Formula = sourcestring
Else
'This is a value
Sheets("MySheet").ListObjects(1).ListColumns("Next").DataBodyRange(row).Value = soureString
End If
once I am done writing a row, I loop to the start and
Dim newRow AS listrow
Set newRow = Sheets("MySheet").Listrows.Add(AlwaysInsert:=False)
row = newRow.Index
But this time when I run the process. this is what I get:
B1.Formula = "=A5"
B2.Formula = "=A5"
B3.Value = ""
B4.value = "=A5"
Why are my formula values all changing to the same value when I use a table instead of a range?
I had the same issue when populating a ListObject (Table) from an Excel Add-in, setting AutoFillFormulasInLists was the solution.
My workaround is to save the current setting, set AutoFillFormulasInLists to false, populate the table with data, formulas etc, then set AutoFillFormulasInLists back to the original setting.
bool OriginalAutoFillFormulaInListsFlag = app.AutoCorrect.AutoFillFormulasInLists;
app.AutoCorrect.AutoFillFormulasInLists = false;
//[ListObject population code....]
if (OriginalAutoFillFormulaInListsFlag == true)
{
app.AutoCorrect.AutoFillFormulasInLists = true;
}
Hope this helps someone.
I faced a similar issue. Ideally you could tell excel to stop doing this but I haven't been able to figure out how. Supposedly doing the following is supposed to keep excel from copying the formulas:
xlApp.AutoCorrect.AutoFillFormulasInLists = false
but it didn't work for me.
Using the answer from this question How to create running total using Excel table structured references? helped me. It doesn't feel like the ideal solution but it does do the job.
I used this formula where Weight is a column name from my table. #This Row is a "Special item specifier" and has a special meaning. The syntax looks a little funky because it's what's called a Structured Reference:
=AVERAGE(INDEX([Weight],1):[[#This Row],[Weight]])
The INDEX([Weight],1) part gives the reference for the 1st row in the Weight column
While the [[#This Row],[Weight]] part gives the reference for the current row in the Weight column.
So for example, if Weight is column J, and the current row is, say, 7 then this is equivalent to
=AVERAGE(J1:J7)
and on the 8th row it will be equivalent to
=AVERAGE(J1:J8) and so on
I have found that the only way to solve the problem of formulas changing in Excel Tables when you insert in VBA is to insert at the first row of the table, NOT the bottom or the middle. You can sort after.
And I always select or reference the EntireRow to do my insert in the Worksheet object not in the table itself. I always put a table in its own Worksheet anyway using xx.Entirerow.Insert.
I am writing a UDF for Excel 2007 which I want to pass a table to, and then reference parts of that table in the UDF. So, for instance my table called "Stock" may look something like this:
Name Cost Items in Stock
Teddy Bear £10 10
Lollipops 20p 1000
I have a UDF which I want to calculate the total cost of all the items left in stock (the actual example is much more complex which can't really be done without very complex formula)
Ideally the syntax of for the UDF would look something like
TOTALPRICE(Stock)
Which from what I can work out would mean the UDF would have the signature
Function TOTALPRICE(table As Range) As Variant
What I am having trouble with is how to reference the columns of the table and iterate through them. Ideally I'd like to be able to do it referencing the column headers (so something like table[Cost]).
This is very basic (no pun intended) but it will do what you describe. For larger tables it may become slow as under the hood it's going back and forth between the macro function and the worksheet, and that kind of activity adds up.
It assumes that you have one row of headers and one column of names (hence the For loop variables starting from 2).
There are all kinds of things that might be necessary - we can save those for another question or another round on this one.
Note that the function returns a "Variant", btw...
Public Function TotalPrice(table As Range) As Variant
Dim row As Long, col As Long
Dim total As Double
For row = 2 To table.Rows.Count
For col = 2 To table.Columns.Count
TotalPrice = TotalPrice + table.Cells(row, col) * table.Cells(row, col + 1)
Next
Next
End Function
Note: I dont have Excel 2007 and I am trying to write this using MSDN doc on the web.
Looks like the range will have ListColumns collection
So, the syntax could be table.ListColumns("Cost").
Does this work?