i want to be able to initialize an array to store the values of a conversion. but i don't know how many values there will be until compile time so i want the range to go from
pseudo-code:
1 to <some expression>
namely i want it as
Dim Colvals(1 To Len(EndColumn)) As Integer
but when the code is sent to compile it throws
Constant Expression required
any idea how to do it? i really don't want to limit the versatility of the program by forcing the specification of the range.
You want to redimension your array using a Redim statement:
Dim Colvals() As Integer
ReDim Colvals(1 To Len(EndColumn))
It seems strange that it requires a Constant for the Dim and not the Redim, but it's true.
Related
I am trying to create an array of a user set length that users can add values to that will be saved and output on multiple sheets. I am very new to VBA so I do not know if what I am trying to do is possible but I have tried a few methods unsuccessfully.
This is the code I have so far
Sub addCost()
Dim costArray() As Variant
ReDim Preserve costArray(1 To Range("b2").Value)
For i = 1 To Range("b2").Value
costArray(i) = 0
Next i
Dim newCost As Variant
Dim costYear As Variant
newCost = InputBox("New cost amount:")
costYear = InputBox("Year new cost is active:")
costArray(costYear) = newCost
End Sub
Here is what the input tab looks like in excel
With the length of the array being the project lifespan and the add new cost activating the code, clear costs are still in progress. Is there a way for the array to store after multiple executions of the addCost sub?
Thanks!
This link Microsoft shows some methods of store values after the macro ending (in your case, sub addCost)
I think the first solution will be good for you.
Other solutions is use Access to store data (specially if you need these data over time) or a new and clean worksheet where you can store array entries in a cell (This is a very practical solution if the number of entries does not get too big)
I have a case where I have a pre-defined set of values/codes what in a combination make some message. I also have an incoming file that I have to analyze on the codes, compare the sets against predefined values. The problem is that the incoming file doesn't exactly match my library:
In my library I have set of 4 columns and each row has it's unique meaning. I want to get that meaning as a string to further proceed with calculations. The problem is that the incoming file is not consistent. It doesn't follow exact sequence as in pre-defined file.
I need to compare them regardless of sequence. After being matched I want to grab corresponding Meaning from Library and proceed working with Case in my file.
Any ideas how to implement it in VBA?
Offhand, you could create a VBA function that would return a string representing the unique values.
If there is some character that will never be in the values, you could delimit the values with that character (such as _):
Function GetUniqueValuesString(rng As Range) As String
Dim rngValues() As Variant
rngValues = rng.Value
' The following line requires a reference to Microsoft Scripting Runtime
' (via Tools -> References...)
Dim dict As New Scripting.Dictionary
'The function only parses the first row of the range
Dim i As Integer
For i = 1 To UBound(rngValues, 2)
dict(rngValues(1, i)) = 1 ' 1 here is a dummy value
Next
GetUniqueValuesString = Join(dict.Keys, "_")
End Function
(If every value is always the same number of characters, you could simply join them, without any delimiter.)
Using this function against a horizontal cell range:
=GetUniqeValuesString(A4:D4)
should return a string with only the unique values:
BGAA_TGHJ_WETY
If you apply this function to both the library rows and the file rows, you should be able to match on the function's returned value.
Note that the function has a few limitations that might need to be resolved:
It assumes the order of the values will be the same. In other words, BGAA, TGHJ, WETY will resolve to a different string than BGAA, WETY, TGHJ.
The function only joins the first row; other rows are ignored.
I declare a date array as such:
Dim date_array() as Date
It's goal is to store dates found in a range.
Dim date_range As String
I declare it as a string because I have an input form where a user specifies the range of dates (e.g. A1:A5).
Then I calculate how many cells are in the range and specify the size of the date_array.
ReDim date_array(Range(date_range).Cells.count)
So far so good. I then loop through each element of date_array and add the date from the range.
Dim i As Long
i = 0
For Each r In ThisWorkbook.Worksheets("Name").Range(date_range)
date_array(i) = r.Value
i + i + 1
Next r
However, when I do a MsgBox(date_array(i)) during this loop, I get a value of 12:00:00 AM instead of the date I want (e.g. 2/2/2019) which tells me something is getting lost in translation.
I get the correct result if I do MsgBox(r.Value)... so it seems like something about the way I'm assigning the date to the array is wrong.
Has anyone run into an issue like this before? How can I fix it?
The larger goal is to map data between two files using date + a naming convention as a validation, so I need the array to store the correct date in a date format so it can be compared to a different cell value later.
Thank you,
So I have a Variant that is storing keys from a Dictionary. I need to put these values into a table but as far as I can tell the data source for a table has to be a range. Is there anyway around this? If not, is there a way to convert my variant to a range?
(Extra details about the Dict and Variant)
Both rely on imported data so there are no fixed values or even number of values, making my issue that much more complicated.
I've tried looking around for answers to this as I am at a complete loss - this is well beyond my current knowledge of vba - but what little I did find didn't seem to work.
Here's the code (only for creating the table but can provide more if needed) without any lines trying to convert the xInput. xInput is the Variant and hashTbl is the Dictionary.
ReDim xInput(0 To hashTbl.Count - 1) 'Redefine xInput as hashTbl values
For i = 0 To hashTbl.Count - 1
xInput(i) = hashTbl.Keys(i)
Next i
Set objTable = ActiveSheet.ListObjects.Add(xlSrcRange, xInput, Selection, , xlYes)
objTable.TableStyle = "TableStyleMedium2"
Of course, I want the table to be populated with the data contained in xInput but all I get is "Runtime Error - 5 Invalid Procedure Call or Argument"
Any help would be much appreciated.
I am attempting to write some excel vba code that will process the content of certain columns of data. Given the worksheet has some level of dynamic change (columns added and removed from time to time), I want my code to "find" the specific columns by their header names, and ultimately return the column number. My File has roughly 50 columns.
The problem is this: My code works just fine to find many of the columns (headers) I am interested in returning the column index, but some of the columns "while clearly existing", will return Nothing and thus, throws the runtime 91 error.
I can say, without a doubt that when I execute the .find, that truly, the columns DO exist (like the Comments column). I can randomly change the failing hdr search column to a different header name, passing it to the function in the code and some columns are found just fine, and other, cause the runtime error. I have checked the "failing" headers for special characters, blanks, LF's etc. No luck. Even tried re-ordering the 4 rows using FindColHdrNum function. Again, no luck.
Was hoping fresh eyes may provide answer. Simplified code is below which is triggered by a button on main excel worksheet. I have not worked with functions much in VBA, and even where the function does not generate the Runtime Error, it is not returning the column value, but this is a secondary problem I can work on once I get the find code not blowing up (returning 0).
Sub Button119_Click()
Dim L4RankCol As Integer
Dim DecomDriverCol As Integer
Dim SupTermImpactYrCol As Integer
Dim Comments As Integer
Dim L3RankCol As Integer
L4RankCol = FindColHdrNum("L4 Rank") '<-- This works
DecomDriverCol = FindColHdrNum("Decom Driver") '<-- This works
SupTermImpactYrCol = FindColHdrNum("Support Termination Impact Yr") '<-- This works
Comments = FindColHdrNum("Comments") '<-- This does not work
End Sub
Function FindColHdrNum(strHdr As String) As Integer
Dim rngAddress As Range
Set rngAddress = Range("Headers").Find(strHdr)
FindColumnHdrNum = rngAddress.Column '<--runtime error is caused by Nothing returned
End Function
Issue turns out to be a spurious line feed that was embedded in the header. It was strange as I kept re-typing it, but of course, I would always start at the "first letter" of the "comment" header, when in fact, the character preceded that. Thanks to all, for the help!
The name of your function is FindColHdrNum but you wrote this into the function:
FindColumnHdrNum = rngAddress.Column
Instead of:
FindColHdrNum = rngAddress.Column