I am facing some issues with the application.match function. Type mismatch.
What is the type of data that application.match returns? an integer?
Any way that I can change the type of l and k below to allow me to work with them using cells(l,k)?
Sub otcheck()
Dim i As Integer
Dim j As Integer
For i = 384 To 395
j = check(i)
Range("O9") = mthdate(j)
Range("O10") = mthdate(j - 1)
If Range("O10") = #12:00:00 AM# Then
l = 9
Else
l = Application.Match(Range("O10"), Range("B9:B500"), 0)
End If
k = Application.Match(Range("O9"), Range("B9:B500"), 0)
Cells(i, 4) = Application.Sum(Range(Cells(l, 14), Cells(k, 14)))
'this above line is having the type mismatch issue
'guessing is due to the l and k variables
Next i
Range("o9:P10") = ""
End Sub
Enter 1 in a cell, select it then enter in the Immediate window:
? typename(application.match(1,selection,0))
outputs "Double"
You should use a Variant though, so you can test the return value for an error in the case where there's no match found:
Dim l As Variant
l = Application.Match(Range("O10"), Range("B9:B500"), 0)
If IsError(l) Then
'no match!
Else
'use l
End If
Don't forget that (for example) l / k values of 1 would correspond to Row9, not Row1 (because your lookup range is B9:B500)
Related
I have the following code throwing a Type MisMatch Error on the line highlighted below. The code is supposed to simply identify empty elements in the input array (stat5) and replace them with a single period in the output array (ArrayOut). However, when it encounters the empty element in position (9,2) of stat5, it throws the Type MisMatch error:
From what I have read about the Type MisMatch error, it sounds like data assigned to a variable does not match the type of the variable. However, in my case, I am encountering the error EVEN when I attempt to simply call the value of stat5(9,1) in the Debug.Print statement below. It hangs on the Print statement (which is not an assignment statement, so I can't figure out what is mismatching with what):
Here is the code:
ReDim ArrayOut(1 To X1N, 1 To 1)
For i2 = 1 To X1N
If Len(Trim(stat5(i2, 2))) = 0 Then
ArrayOut(i2, 1) = "."
Else
ArrayOut(i2, 1) = stat5(i2, 2)
End If
Next i2
Here is the data in the input array (In this particular case, the non-missing values of the 2nd column of the array are constant, but this is not always the case). These are the values of stat5 when the error occurs in iteration 9 of the loop:
1 0.500285714
2 0.500285714
3 0.500285714
4 0.500285714
5 0.500285714
6 0.500285714
7 0.500285714
8 0.500285714
9
10 0.500285714
=========================================================
Here is the code that sets up stat5. All of this code runs without error:
Dim stat1 As Variant
Dim stat2 As Variant
Dim stat3 As Variant
Dim stat4 As Variant
Dim stat5 As Variant
'ReCombine Results for Final Printing
'Add ObsNum to each
'Prediction Set Results
ReDim stat1(1 To X3N, 1 To 2)
For i2 = 1 To X3N
stat1(i2, 1) = X3(i2, 1)
If Pred = True Then
If NumberOfArrayDimensions(ArrayPredIn) = 1 Then
stat1(i2, 2) = ArrayPredIn(i2)
Else
stat1(i2, 2) = ArrayPredIn(i2, 1)
End If
Else
stat1(i2, 2) = ""
End If
Next i2
'Estimation Set ResultS
ReDim stat2(1 To UBound(X4, 1), 1 To 2)
If NumberOfArrayDimensions(ArrayEstIn) = 1 Then
For i2 = 1 To UBound(X5, 1)
stat2(i2, 1) = X4(i2, 1)
stat2(i2, 2) = ArrayEstIn(i2)
Next i2
Else
For i2 = 1 To UBound(X5, 1)
stat2(i2, 1) = X4(i2, 1)
stat2(i2, 2) = ArrayEstIn(i2, 1)
Next i2
End If
'Concatenate stat1, stat2, stat3
ReDim stat5(1 To X1N, 1 To 2)
stat5 = Combine(stat1, stat2)
QuickSortArray stat5, , , 1
Here is the Combine function:
Function Combine(a As Variant, b As Variant, Optional stacked As Boolean = True) As Variant
'assumes that A and B are 2-dimensional variant arrays
'if stacked is true then A is placed on top of B
'in this case the number of rows must be the same,
'otherwise they are placed side by side A|B
'in which case the number of columns are the same
'LBound can be anything but is assumed to be
'the same for A and B (in both dimensions)
'False is returned if a clash
Dim lb As Long, m_A As Long, n_A As Long
Dim m_B As Long, n_B As Long
Dim m As Long, N As Long
Dim C As Variant
If TypeName(a) = "Range" Then a = a.value
If TypeName(b) = "Range" Then b = b.value
lb = LBound(a, 1)
m_A = UBound(a, 1)
n_A = UBound(a, 2)
m_B = UBound(b, 1)
n_B = UBound(b, 2)
If stacked Then
m = m_A + m_B + 1 - lb
N = n_A
If n_B <> N Then
Combine = False
Exit Function
End If
Else
m = m_A
If m_B <> m Then
Combine = False
Exit Function
End If
N = n_A + n_B + 1 - lb
End If
ReDim C(lb To m, lb To N)
For i = lb To m
For j = lb To N
If stacked Then
If i <= m_A Then
C(i, j) = a(i, j)
Else
C(i, j) = b(lb + i - m_A - 1, j)
End If
Else
If j <= n_A Then
C(i, j) = a(i, j)
Else
C(i, j) = b(i, lb + j - n_A - 1)
End If
End If
Next j
Next i
Combine = C
End Function
=========================================================================
UPDATE: When I check the type of each element of stat5, the type of element (9,2) is 8204 (while all the other (i2,2) elements are 5 = vbdouble). However, I'm not sure what this means: Has a multi-element array been saved to the (9,2) element of the array stat5? Is that possible?
I tried wrapping all of the calls to stat5(i2,2) with CStr(), hoping to convert the info in (9,2) to a string, but this also gives the same Type MisMatch error.
Locals window output:
===============================================================================
Results from the Locals window:
However, the variable type according to VarType() for elements (1-8,2) is vbDouble ("5") which seems to contradict the results in the Locals window:
===============================================================================
UPDATE: I was able to reproduce the error with stat1 BEFORE the Combine function was used to create stat5. Therefore, I do not believe that the problem is with the Combine function.
I have a workbook where I want to find the differences of two sheets by looking at the company name and their corporate registration number and then type the differences on the third sheet.
I have tried the code in another workbook with only 143 rows, which works perfectly, but when I try it on the real workbook with 10,000 rows I get a "type mismatch error". Also if I use other columns than the CVR and Firm columns the code also works.
The CVR is numbers and Firms are strings (firm names). I get the
type mismatch error
on the line I marked **. Does somebody know why I get this error?
Sub ComCVR()
Dim CVR1()
Dim CVR2()
Dim Firm1()
Dim Firm2()
Dim n As Long, m As Long
Dim i As Double, j As Double
Dim intCurRow1 As Integer, intCurRow2 As Integer
Dim rng As Range, rng1 As Range
Set rng = ThisWorkbook.Sheets("Last month").Range("A11")
Set rng1 = ThisWorkbook.Sheets("Current month").Range("A11")
n = rng.CurrentRegion.Rows.Count
m = rng1.CurrentRegion.Rows.Count
ReDim CVR1(n)
ReDim Firm1(n)
ReDim CVR2(m)
ReDim Firm2(m)
ThisWorkbook.Sheets("CVR").Range("A1") = "Flyttet CVR"
ThisWorkbook.Sheets("CVR").Range("B1") = "Flyttet Firmanavn"
ThisWorkbook.Sheets("CVR").Range("A1:B1").Interior.ColorIndex = 3
ThisWorkbook.Sheets("CVR").Range("C1") = "Nye CVR"
ThisWorkbook.Sheets("CVR").Range("D1") = "Nye Firmanavn"
ThisWorkbook.Sheets("CVR").Range("C1:D1").Interior.ColorIndex = 4
ThisWorkbook.Sheets("CVR").Range("A1:D1").Font.Bold = True
' Inset data to arrays
For i = 0 To n
CVR1(i) = ThisWorkbook.Sheets("Last month").Cells(12 + i, 5)
Firm1(i) = ThisWorkbook.Sheets("Last month").Cells(12 + i, 4)
Next
For i = 0 To m
CVR2(i) = ThisWorkbook.Sheets("Current month").Cells(12 + i, 5)
Firm2(i) = ThisWorkbook.Sheets("Current month").Cells(12 + i, 4)
Next
intCurRow1 = 2
intCurRow2 = 2
'Old
For i = 0 To n
For j = 0 To m
If Firm1(i) = ThisWorkbook.Sheets("Current month").Cells(12 + j, 4) Then '** Error raised here
Exit For
End If
If j = m Then
ThisWorkbook.Sheets("CVR").Cells(intCurRow1, 1) = CVR1(i)
ThisWorkbook.Sheets("CVR").Cells(intCurRow1, 2) = Firm1(i)
intCurRow1 = intCurRow1 + 1
End If
Next j
Next i
'new
For i = 0 To m
For j = 0 To n
If Firm2(i) = ThisWorkbook.Sheets("Last month").Cells(12 + j, 4) Then
Exit For
End If
If j = n Then
ThisWorkbook.Sheets("CVR").Cells(intCurRow2, 3) = CVR2(i)
ThisWorkbook.Sheets("CVR").Cells(intCurRow2, 4) = Firm2(i)
intCurRow2 = intCurRow2 + 1
End If
Next j
Next i
Columns("A:B").Select
ActiveSheet.Range("$A:$B").RemoveDuplicates Columns:=1, Header:=xlNo
Application.DisplayAlerts = False
Columns("C:D").Select
ActiveSheet.Range("$C:$D").RemoveDuplicates Columns:=1, Header:=xlNo
Application.DisplayAlerts = False
End Sub
Whenever an error happens, the best way is to google it. This is what it says in the documentation of VBA for Type mismatch:
Cause: The variable or property isn't of the correct type. For example, a variable that requires an integer value can't accept a string value unless the whole string can be recognized as an integer.
In the case of the code, it happens, when an array is compared with excel cell. Now the trick - in order to see why it happens, see what is in these:
Debug.Print ThisWorkbook.Sheets("Last month").Cells(12 + i, 4)
Debug.Print Firm1(i)
and the after the error runs, take a look at the immediate window (Ctrl+G). It it quite possible, that there is an error in the excel cell, thus it cannot be compared. This is some easy way to avoid it, if this is the case:
Sub TestMe()
Dim myRange As Range
Set myRange = Worksheets(1).Cells(1, 1)
myRange.Formula = "=0/0"
If Not IsError(myRange) Then
Debug.Print CBool(myRange = 2)
Else
Debug.Print myRange.Address; " is error!"
End If
End Sub
VBA Newbie here with a basic question I've been struggling to find the answer on:
I'm trying to run a loop in VBA that looks up a string (or word) and if that word is found, a specified letter has to appear in a cell in the column beside it. This works fine when I use a specific cell reference (eg Cells(72, 10)), but as soon as I try to loop it using an index (eg Cells(i, 10), it gives an error 13 - type mismatch.
The 'strings' I'm looking up are outputs (either "Peak" or "Trough") from another macro I wrote as a basic calculation function in excel. Is the error as a result of trying to reference a different data type than the "Cells" function can recognise? Or is there just a better way to run my loop? Following are the macro and my loop.
Function FTrough(tmin2, tmin1, t, tplus1, tplus2)
If t < tmin2 And t < tmin1 And t < tplus1 And t < tplus2 Then
FTrough = "Trough"
Else
FTrough = ""
End If
End Function
And the loop":
Sub Lookup()
Dim i As Integer
Dim j As Integer
Dim c As Integer
c = ActiveWorkbook.Worksheets.Count
For i = 1 To c
For j = 2 To 141
If Worksheets(i).Cells(j, 10) = "Trough" Then
Worksheets(i).Cells(j, 12) = "T"
End If
If Worksheets("Austria").Cells(j, 11) = "Peak" Then
Worksheets("Austria").Cells(j, 12) = "P"
End If
Next j
Next i
End Sub
Any help appreciated
I cannot comment because my reput is lower than 50, so here is my answer.
Basically your code works perfectly. I tested it with Excel 2013/VB6 as follows:
Sub Lookup()
Dim i As Integer
Dim j As Integer
Dim c As Integer
c = ActiveWorkbook.Worksheets.Count
For i = 1 To c
For j = 2 To 141
If Worksheets(i).Cells(j, 1) = "Trough" Then
Worksheets(i).Cells(j, 2) = "T"
End If
If Worksheets("Austria").Cells(j, 1) = "Peak" Then
Worksheets("Austria").Cells(j, 2) = "P"
End If
Next j
Next i
End Sub
The function to write the values in Excel:
Public Function X(tmin2, tmin1, t, tplus1, tplus2)
If t < tmin2 And t < tmin1 And t < tplus1 And t < tplus2 Then
X = "Trough"
Else
X = ""
End If
End Function
The values in excel were created by custom as well as e.g. =X(100;100;1;100;100).
I have data stored in some column (Say, Column A). The length of Column A is not fixed (depends on previous steps in the code).
I need a histogram for the values in Column A, and have it in the same sheet. I need to take the values in column A, and automatically compute M Bins, then give the plot.
I looked online for a "simple" code, but all codes are really fancy, with tons of details that I don't need, to the extent that I am not even able to use it. (I am a VBA beginner.)
I found the following code that seems to do the job, but I am having trouble even calling the function. Besides, it only does computations but does not make the plot.
Sub Hist(M As Long, arr() As Single)
Dim i As Long, j As Long
Dim Length As Single
ReDim breaks(M) As Single
ReDim freq(M) As Single
For i = 1 To M
freq(i) = 0
Next i
Length = (arr(UBound(arr)) - arr(1)) / M
For i = 1 To M
breaks(i) = arr(1) + Length * i
Next i
For i = 1 To UBound(arr)
If (arr(i) <= breaks(1)) Then freq(1) = freq(1) + 1
If (arr(i) >= breaks(M - 1)) Then freq(M) = freq(M) + 1
For j = 2 To M - 1
If (arr(i) > breaks(j - 1) And arr(i) <= breaks(j)) Then freq(j) = freq(j) + 1
Next j
Next i
For i = 1 To M
Cells(i, 1) = breaks(i)
Cells(i, 2) = freq(i)
Next i
End Sub
And then I try to call it simply by:
Sub TestTrial()
Dim arr() As Variant
Dim M As Double
Dim N As Range
arr = Range("A1:A10").Value
M = 10
Hist(M, arr) ' This does not work. Gives me Error (= Expected)
End Sub
A little late but still I want to share my solution. I created a Histogram function which might be used as array formula in the excel spread sheet. Note: you must press
CTRL+SHIFT+ENTER to enter the formula into your workbook. Input is the range of values and the number M of bins for the histogram. The output range must have M rows and two columns. One column for the bin value and one column for the bin frequency.
Option Explicit
Option Base 1
Public Function Histogram(arr As Range, M As Long) As Variant
On Error GoTo ErrHandler
Dim val() As Variant
val = arr.Value
Dim i As Long, j As Integer
Dim Length As Single
ReDim breaks(M) As Single
ReDim freq(M) As Integer
Dim min As Single
min = WorksheetFunction.min(val)
Dim max As Single
max = WorksheetFunction.max(val)
Length = (max - min) / M
For i = 1 To M
breaks(i) = min + Length * i
freq(i) = 0
Next i
For i = 1 To UBound(val)
If IsNumeric(val(i, 1)) And Not IsEmpty(val(i, 1)) Then
If val(i, 1) > breaks(M) Then
freq(M) = freq(M) + 1
Else
j = Int((val(i, 1) - min) / Length) + 1
freq(j) = freq(j) + 1
End If
End If
Next i
Dim res() As Variant
ReDim res(M, 2)
For i = 1 To M
res(i, 1) = breaks(i)
res(i, 2) = freq(i)
Next i
Histogram = res
ErrHandler:
'Debug.Print Err.Description
End Function
Not 100% sure as to the efficacy of that approach but;
Remove the parens as your calling a sub; Hist M, arr
M is declared as double but received by the function as a long; this won't work so declare it in the calling routine as long
You will need to recieve arr() As Variant
Range -> Array produces a 2 dimensional array so the elements are arr(1, 1) .. arr(n, 1)
When I compare the value of a cell that contains ? to a variable, it always returns true. Is there any way I can prevent this? Here is my current code:
'Option Explicit
Dim hws As Worksheet
Set hws = ActiveSheet
Dim rng As Range, rng2 As Range
Dim letters(2, 2)
alpha = Range("CipherTable").Value
For x = 1 To 7
For y = 1 To 7
If alpha(x, y) = rng.Cells(i, j + 1).Value Then
letters(2, 1) = x
letters(2, 2) = y
End If
Next y
Next x
alpha, by the way, looks like this:
A B C D E F G
H I J K L M N
O P Q R S T U
V W X Y Z 1 2
3 4 5 6 7 8 9
0 ; : ' " . ,
( ) _ - + ? !
This always returns A, which is in alpha(1,1). Come to think of it, since they each go to seven, I don't know why it don't come back with !. How can I get around this and make it return true only when it actually matches?
As far as I understand you want to create a substitution algorithm. If there is no specific reason to use a two dimensional cipher table I would rather use a one dimensional approach like the following:
Function Cipher(Argument As String) As String
Dim Model As String
Dim Subst As String
Dim Idx As Integer
Dim MyPos As Integer
Cipher = ""
' note double quotation mark within string
Model = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890;:'"".,()_-+?!"
Subst = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890;:'"".,()_-+?!"
For Idx = 1 To Len(Argument)
' get position from Model
MyPos = InStr(1, Model, UCase(Mid(Argument, Idx, 1)))
' return character from substitution pattern
If MyPos <> 0 Then Cipher = Cipher & Mid(Subst, MyPos, 1)
Next Idx
End Function
calling this function with
Sub Test()
Debug.Print Cipher("The quick brown (?) fox 123 +-")
End Sub
results in THEQUICKBROWN(?)FOX123+- (because we don't allow blanks in Model or Subst)
Now change Subst to
Subst = "!?+-_)(,.""':;0987654321ZYXWVUTSRQPONMLKJIHGFEDCBA"
result is 4,_73.+'?6910GBF)9ZWVUCD
if you feed the above into the cipher function, you end up again with THEQUICKBROWN(?)FOX123+- as you would expect from a symetrical substitution.
I tried the following, and got the expected result (it was able to find the question mark):
(1) Created CipherTable range in worksheet, as above;
(2) Created a function QM similar to code above;
(3) Entered a formula in the style of =QM(cell-ref).
It worked fine. Function QM:
Public Function QM(theChar)
Dim CipherTable
Dim x As Integer
Dim y As Integer
CipherTable = Range("CipherTable").Value
For x = 1 To 7
For y = 1 To 7
If CipherTable(x, y) = theChar Then
QM = "X" & x & "Y" & y
Exit Function
End If
Next y
Next x
QM = ""
End Function
====
I also tried something more direct, and got the response expected:
Public Sub QM2()
Dim questMark As Range
Dim someChar As String
Set questMark = Range("CipherTable").Cells(7, 6)
someChar = "A"
Debug.Print questMark = someChar
End Sub