Checking if values from two arrays are equal. They are but VBA thinks they're not (UPDATE: Resolution at bottom) - vba

I've run into a strange problem:
I have two separate arrays with 3 attributes I'm trying to match to determine if all three attributes match, partial matches, or no matches.
I have a loop to loop through the values in the first array and a second nested loop within that loop to loop through the second array for each line of the first array.
Here's where it get's weird: I have three If-statement gates that check if the first attribute (amount) is equal in each of the arrays, then the second attribute (trace), and finally the last attribute (customer).
I have a line item in one array that matches on the amount (as it should), but then fails on the trace check (where it shouldn't).
I've used Debug.Print to see if the values are the same. They are. I checked that the format from the original data is the same (i.e. no spaces/hidden characters etc.). I made sure that when the array is populated from the cells, it uses the .Value method.
Even though I've checked all these, and the Debug.Print shows they are the same, it fails the check when comparing the two values.
Here's the code:
For RemMatchLoop = LBound(RemAmtMatchArray, 2) To UBound(RemAmtMatchArray, 2) Step 1
PerfectMatchFound = False
For MMMatchLoop = LBound(MMAmtMatchArray, 2) To UBound(MMAmtMatchArray, 2) Step 1
If MMAmtMatchArray(MMAmountCol, MMMatchLoop) = RemAmtMatchArray(RemAmountCol, RemMatchLoop) Then
Debug.Print "MM Trace: " & MMAmtMatchArray(MMTraceCol, MMMatchLoop)
Debug.Print "Rem Trace: " & RemAmtMatchArray(RemTraceCol, RemMatchLoop)
If MMAmtMatchArray(MMTraceCol, MMMatchLoop) = RemAmtMatchArray(RemTraceCol, RemMatchLoop) Then
If MMAmtMatchArray(MMCustomerCol, MMMatchLoop) = RemAmtMatchArray(RemCustomerCol, RemMatchLoop) Then
ReDim Preserve RemPerfectMatchArray(1 To RemLastCol, 1 To RemPerfectMatchCount) As Variant
For RemPerfectMatchColFill = 1 To RemInBalanceCol Step 1
RemPerfectMatchArray(RemPerfectMatchColFill, RemPerfectMatchCount) = RemAmtMatchArray(RemPerfectMatchColFill, RemMatchLoop)
If RemPerfectMatchColFill = RemAmountCol Then
Debug.Print "Perfect Match Amount: " & RemPerfectMatchArray(RemPerfectMatchColFill, RemPerfectMatchCount)
End If
Next RemPerfectMatchColFill
RemPerfectMatchCount = RemPerfectMatchCount + 1
PerfectMatchFound = True
End If
End If
End If
Next MMMatchLoop
Here's what the Debug.Print has spit out regarding the line item in question:
MM Trace: 1234
Rem Trace: 1234
So, both traces are the same, but when it passes the line:
If MMAmtMatchArray(MMTraceCol, MMMatchLoop) = RemAmtMatchArray(RemTraceCol, RemMatchLoop) Then
It detects them as not-equal.
UPDATE: One type is Double and the other is String. Not sure why, because the data the array resulting in a String value pulls from is not Text format and is a number.
Additionally, when the data is populated into the array, it uses the .Value method, as seen below:
For RemAmtMatchColFill = 1 To RemLastCol Step 1
RemAmtMatchArray(RemAmtMatchColFill, RemAmtMatchCount) = RemWS.Cells(RemAmtMatchLoop, RemAmtMatchColFill).Value
Next RemAmtMatchColFill
Not sure why then it's detecting a string...
Any help would be appreciated, as I'm completely baffled.
RESOLUTION
After using Typename() suggested in the comments to identify what types are being compared, it was determined that the Variant array was converting Currency data types in both source data into Double type in one array and String type in another. While it's strange that it's doing this, by using CStr() to convert both values to strings while comparing fixed the issue.
Thanks!
Joe

Related

Indexing through an array by column number

I've looked up info with regards to column attributes. I'm trying to perform some insertions and copying of information within an array. The crux of my issue is that I want o nest some actions within a loop, so I need to index the column by a number not letter.
The first thing I do is find a starting point based upon a header name:
Dim EnvCondCol As String
Dim EnvCondColN As Long
Dim lColVVS As Integer
lColVVS = VET_VS.UsedRange.Columns.Count ' finds last column
For n = 1 To lColVVS
If UCase(VET_VS.Cells(3, n).Value) Like "*ENVIRONMENTAL CONDITION*" Then ' All Caps when using "like"
EnvCondCol = Split(VET_VS.Cells(3, n).Address, "$")(1)
EnvCondColN = Range(EnvCondCol & 1).Column
Exit For
End If
Next n
This works and when I watch EnvCondCol and EnvCondColN is can see EnvCondCol = "I" and EnvCondColN = "9"
Eventually, I want to insert a new column, and this line generates a syntax error:
VET_VS.Range(Columns.(EnvCondColN)).EntireColumn.Insert
When I watch EnvCondColN, it is a number, and I have tried changing the dim to other types, such as integer
Also elsewhere, I want to copy information from a cell into another cell from within a loop. This generates a syntax error.
VET_VS.Range(Columns.(EnvCondColN + i)).Copy VET_VS.Range(Columns.(EnvCondColN + j))
If I replace EnvCondColN with a value like 5, then this works. Example: VET_VS.Range(Columns.(5)).EntireColumn.Insert
Why isn't the variable working as a column reference??
Thank you all for looking!
change
VET_VS.Range(Columns.(EnvCondColN)).EntireColumn.Insert
to
VET_VS.Columns(EnvCondColN).EntireColumn.Insert

Excel VBA Nested For Loop Returns Run Time Error 9

After the 12th found match of the loop, I have a Run-time Error 9 on the rptVals array. Basically, the rptcount hits 247 - where rptRows has a count of 246. I have tried doubling and quadrupling the size of rptRows, and each time I pass the 12th match I get the error. I tried loading a different data set that has one more row of data than the first workbook, and I get the error there after the 13th match - again regardless of rptRows count size, but always matching report counts maximum count.
Any ideas why this is happening? Also, I'm a chemist, not a programmer, so sorry if this isn't the prettiest code or the most efficient or whatever. If it works, I'm happy. Also, I've been made aware of Dictionaries, but I have a better grasp on arrays and loops than I do dictionaries (which obviosly isn't saying much, but oh well).
Sub PrntFllEle()
With Workbooks("Full Element Analysis Current").Worksheets("All _
Samples")
rptRows = Range("H6:IS6").Columns.Count 'here is the start of the
'problem. rptRows = 246
'rptrng = rptRows * 2 I made this variable to double/quadruple the _
size of rptRows count
rptVals = .Range("H6:IS6" & rptRows).Value
End With
With Workbooks(FlNm).Worksheets("Report")
'rEleAn, seen below the range of data captured in a separate sub.
'This will also have an associated array ElAr from the other sub.
chkRows = rEleAn.Rows.Count
End With
For rptcount = LBound(rptVals) To UBound(rptVals)
For chkcount = LBound(ElAr) To UBound(ElAr)
If rptVals(1, rptcount) <> "" Then 'I had to include this as _
I have some blank cells _
in array and this was the _
quickest way to deal with it.
'This next line is where the run-time error occurs. rptVals = _
Subscript out of Range and rptcount = 247
'Note, the UBound(rptVals) is 6241.
If rptVals(1, rptcount) = Mid((ElAr(chkcount, 1)), 1, 2) Then
MsgBox rptVals(1, rptcount)
'MsgBox just a place holder for now.
End If
Else
Exit For
End If
Next
Next
End Sub
All variables are global, btw. I've check those values, and everything that could affect this is Long. All arrays are Variants as I have strings and numbers to deal with. Ranges are appropriately Dim As Range.
Your For ... Next construction is defaulting to the first rank of your array. You want the second rank.
For rptcount = LBound(rptVals, 2) To UBound(rptVals, 2)
For chkcount = LBound(ElAr, 1) To UBound(ElAr, 1)

Remove duplicate rows based on dynamic amount of columns

I got the total number of columns, and tried to append it to string in such a way it is 1,2,3,4,5 depending on the number of columns.
Sub DeleteHighlightedRecords()
numofCol = ""
For i = 1 To lcol
numofCol = numofCol & "," & i
Next i
numofCol = Mid(numofCol, 2)
ThisWorkbook.Worksheets(1).Cells.RemoveDuplicates Columns:=Array(numofCol), Header:=xlNo
End Sub
The above code i have will match the combination i placed in Array(), and then remove the duplicates ya? Correct me if i am wrong, however I am getting application-defined error.
How may i set the dynamic numbers of columns into the Array()?
Array(1,2,3) is not the same as Array("1,2,3"). The first will produce an 3-element array containing 1,2 and 3, the second will produce an 1-element array containing the string "1,2,3".
To create an actual array we can do the following:
Dim numOfCol() As Variant 'normally I would choose Long instead of variant but that gave a type mismatch error
Dim i As Long 'always use "Option Explicit" at the top of your module!
ReDim numOfCol(0 To (lcol - 1)) 'has to be 0-based for RemoveDuplicates
For i = 0 To (lcol - 1)
numOfCol(i) = i + 1
Next i
Now as if using a Variant array instead of a Long array and using a 0-based array wasn't enough, RemoveDuplicates apparently also can't handle arguments passed as a reference to a variable instead of a value. To pass a variable as a value rather than a reference, encase it in parentheses. This causes the variable to be evaluated and then passed to the function.
ThisWorkbook.Worksheets(1).Cells.RemoveDuplicates Columns:=(numOfCol), Header:=xlNo

Type mismatch when passing an array

I keep on getting an error when I try and pass this value to an array, essentially I am working with exchange rates, I have the currency in the second dimension of the array ary() and I am looking to retrieve a data point in a table that is 2 cells away from the element stored in the array.
Now I believe the problem has something to do with the value being a number and the array being a variant, however I cannot solve the problem.
Option Explicit
Dim fxary(), y
ws.Select
Set Rng = Sheets("BEXR").Range("C2:C" & Sheets("BEXR").Range("A1").End(xlDown).Row)
For i = 1 To UBound(ary, 2)
If ary(2, i) <> ary(2, UBound(ary, 2)) Then
For Each y In Rng
If Sheets("BEXR").Range(y.Address).Value = ary(2, UBound(ary, 2)) And Sheets("BEXR").Range(y.Address).Offset(0, 1).Value = ary(2, i) Then
fxary() = Sheets("BEXR").Range(y.Address).Offset(0, 2).Value ' error occurring here
fxary = ary(1, i)
End If
Next y
End If
Next
Your comments say that I have omitted all the lines not related to this specific problem, therefore I will post an answer based on the assumption that all the lines that are related to the problem have been included in the code in the question.
The following comments should be made about your code:
You have used Option Explicit but nowhere do you declare the size or type of the variables i and ary.
Nowhere do you specify values for the variable ary.
Your line saying fxary() = Sheets("BEXR").Range(y.Address).Offset(0, 2).Value is trying to assign a scalar to a vector, and will generate a Type Mismatch error.
Your line saying fxary() = Sheets("BEXR").Range(y.Address).Offset(0, 2).Value is immediately followed by a line (fxary = ary(1, i)) replacing the value of fxary with something else, so the first line is redundant.
All your references to Sheets("BEXR").Range(y.Address) can be replaced with y.
You are executing through two loops (from 1 to whatever the second dimension of the undefined variable ary is and, within that loop, through every cell in column C of your sheet), but you are effectively only setting fxary once, i.e. to the value in the undefined variable ary where the first dimension's value is 1 and the second dimension's value is i. (But I haven't been able to wrap my mind around the code enough to be able to work out which value of i that will end up being - I think it's worked out by looking at each row of your sheet that has a different value in column C than in column D, and the value in column C is equal to ary(2, highest value), and then determining the highest value of i such that ary(2, i) will equal the value in column D.)
I believe you need to look at each of the above items before your code will do anything meaningful, but to resolve the specific problem you say you are having:
1) Change your declaration of fxary to
Dim fxary, y
2) Simply remove the line saying
fxary() = Sheets("BEXR").Range(y.Address).Offset(0, 2).Value
as that line is redundant (as I said in one of my earlier points).

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.