Edited to add solution: I was trying to do Sumproduct and I'm a big dummy haha
I'm trying to do a pretty simple calculation in VBA where I need to loop through two ranges and multiply specific cells then add the value to a placeholder value.
The code is:
Dim Input_Cas As Range
Set Input_Cas = Worksheets("Calculations").Range("A2:A51")
Dim Input_Conc As Range
Set Input_Conc = Worksheets("Calculations").Range("C2:C51")
i = 1
Do Until IsEmpty(Range("Input_Cas")(i)) = True
Tkm = Tkm + Range("Input_Tki")(i) * (Range("Input_Conc")(i) / 100)
i = i + 1
Loop
Mix_Tkm = Tkm
The Ranges defined as Input_Conc, Input_Tki, Input_Cas are all in the active sheet and Dim/Set in code above this block.
Tkm is double and Mix_Tkm is a Dim/Set range as well.
The Error 1004 kicks out in the first line of the Do Until ... Loop.
Since the syntax doesn't seem to be causing any issues in the IsEmpty(Range("Input_Cas")(i)) = True I'm not sure why that same syntax doesn't work below it. All cells referenced contain numerical values as well, just in case that is relevant.
I love you wonderful people and thanks for your help in advance.
Edit: The Dim/Set for the ranges are
Dim Input_Cas As Range
Set Input_Cas = Worksheets("Calculations").Range("A2:A51")
Dim Input_Conc As Range
Set Input_Conc = Worksheets("Calculations").Range("C2:C51")
Dim Input_Tki As Range
Set Input_Tki = Worksheets("Calculations").Range("G2:G51")
As suggested I am posting the answer to self for folks from the future.
I was attempting to recreate the Sumproduct function from excel within VBA by making a loop. What I was attempting was more effectively done in excel. I didn't know Sumproduct was a thing and it does exactly what I was attempting.
Thanks to Bigben for providing the solution I couldn't find for myself.
Related
I would like to store the average value for all (numerical, constant) data stored in a range in a variable.
k = average(Range(cells(15, 27)Cells(i-1, 27))
It appears to me that I define the range wrong, where is my syntax error? Thank you very much for your help.
Second iteration:
k = Average(Range(Cells(15, 27))(Cells(i - 1, 27))
It seems that VBA does not understand "Average" as function although I found it online. https://www.mrexcel.com/board/threads/average-a-range-of-cells-in-vba.292819/
These seem to work, you can use the worksheet functions.
Range("H3") = Application.WorksheetFunction.Average(Range("H15:H999"))
Range("H4") = Application.WorksheetFunction.StDev_S(Range("H15:H999"))
I wish I could insert a check for the last filled cell, so that I avoid including any values by chance that are much below the range I want to analyse. Would be great if you had any ideas.
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
I have several designs, and each design has several variables.
Using VBA code, I want to loop thru each design, and assign variables to each of the indices of the one design.
I'm having a hard time getting the array dim statement correct, and correctly calling the nth variable of each design.
I've shown VBA code here that uses a message box to display if I am getting the right value from each j loop, and each design.
Any help?
Dim Design(0 To 9) As Variant
Sub main
Design(1) = Array(4,6,2,1)
Design(2) = Array(8,2,6,9)
For i = 1 To 2
For j = 1 to 4
MsgBox (Design(i)(j-1))
Next j
Next i
End sub
Wow, my apologies. I've been trying for WEEKS to get this to work, and in formatting it for this question, it FINALLY worked! Code is good as is.
Problem - I have around more than 8202 characters in once cell say Range("A1").
Now I would like to copy the content of cell(A1) to cell(A2) using VBA. I'm using below Code
Sheets("XYZ").Range("A2") = Sheets("XYZ").Range("A1")
After the execution of the Code. It gives "Application Defined Or Object Defined Error !!"
Please help/assist with your expert comments.
Observation - If I reduce the length of "A1" cell to 8202 or less then about code works!
I'm Confused. Pls assist.
Change your code to
Sheets("XYZ").Range("A2") = Sheets("XYZ").Range("A1").Value
and it will work.
Not really sure why though, as .Value is the default property of a range.
I was able to duplicate your error with the following:
Sub Test8202Copy()
Dim wks As Worksheet
Set wks = Worksheets("Sheet1")
Dim x As String
For i = 0 To 8202
x = x + "a"
Next i
wks.Range("A1").Value = x
wks.Range("A2") = wks.Range("A1")
End Sub
I was able to solve the error by adding .value to the copy.
Sub Test8202Copy()
Dim wks As Worksheet
Set wks = Worksheets("Sheet1")
Dim x As String
For i = 0 To 8202
x = x + "a"
Next i
wks.Range("A1").Value = x
wks.Range("A2").Value = wks.Range("A1").Value
End Sub
Using an intermediate variable without the use of .Value seems to work:
Dim y As Variant
y = wks.Range("A1")
wks.Range("A2") = y
My guess so far is that 8202 exceed the character limit of the data type used when you don't define .Value. The in cell limit length is 32,767 (MS Excel 2010) which is almost 4x the 8201 value that clears.
#Chris Neilsen provided the most practical and elegant solution to the problem (his code snippet follows):
Sheets("XYZ").Range("A2") = Sheets("XYZ").Range("A1").Value
In order to investigate and understand the possible cause of this strange behavior (may be a bug) of the Range object, I've posted couple comments, which are summarized below:
There is a conceptual difference between the original expression (see below):
Sheets("XYZ").Range("A2") = Sheets("XYZ").Range("A1")
and solution proposed by #Chris Neilsen, namely: original expression is implicitly assigning the Range object var (essentially, a pointer) to another Range object, like demonstrated in the following code snippet with explicit assignment:
Set rng = Sheets("XYZ").Range("A1")
Sheets("XYZ").Range("A2") = rng
while proposed solution explicitly passes the value property. Still, the reason why assigning a Range object failed for a value with string.Length>8202 is currently unclear (it may be caused by some internal nuances of the Excel Range object implementation).
Many thanks for posting this interesting question and fruitful discussion.
Regards,
This limit (see below re excel-2007) is covered in this MSDN article although interestingly it implies a vba array is invoved
Separately as per https://stackoverflow.com/a/13665363/641067 excel-2003 cant handle array strings longer than 911 characters, whereas the article below references 1823 character
SYMPTOMS
When you run a Microsoft Visual Basic for Applications (VBA) macro to transfer data from a VBA array that contains strings of data to a range of cells in a Microsoft Excel worksheet, the data may be truncated (cut off).
Note In Microsoft Office Excel 2003 and in later versions of Excel, you may receive the following error message when you run the VBA macro in the Visual Basic Editor:
Run-time error '1004'
CAUSE
This problem may occur when one of the following conditions is true:
In Excel 2007, the VBA array is longer than 8,203 characters in length.
In Excel 2003 and in earlier versions of Excel, the VBA array is longer than 1,823 characters in length
I have dabbled in vba for a little while, but its uses are mainly to save myself work and make easy things that are not easy to do in vanilla excel. I use SQL a lot and many things that are fascinatingly easy to get in SQL are surprisingly difficult in excel.
I recently made a new file to follow the costs that are generated when someone takes an item from our warehouse. Assuming that everything gets registered correctly I have made an SQL report that spits out different data; among which are pertinent to this question:
An article number
A cost centre
Now, I thought I would improve my file with some autogenerated lists, so I can use it for whatever department not just my own. The difference is that I know roughly the correct article numbers and cost centers of my department.
What I would like to do.
With a list of cost center numbers:
Generate a list of article numbers that are taken from the dump (~10.000 rows) that have been listed on each (specific) cost center. Unique, of course
Use the count of cost centers and the count of article numbers to copy formulas from a sheet with a template...
...then populate the fresh sheet with the cost centers and article numbers. The formulas will then fetch with sumifs from the dump and make nice monthly graphics of it all.
This is getting out of hand with the explanation, because I stranded pretty early doing this:
'-----------------------------------------------
Dim Myworkbook As Workbook
Set Myworkbook = ThisWorkbook
'-
Dim Sheet1 As Worksheet
Dim Sheet2 As Worksheet
Dim Sheet3 As Worksheet
Dim Rgensheet As Worksheet
'-
Set Sheet1 = Myworkbook.Sheets("Sheet1")
Set Sheet2 = Myworkbook.Sheets("00 Underlag")
Set Sheet3 = Myworkbook.Sheets("01 Dump")
Set Rgensheet = Myworkbook.Sheets("RGenInput")
'-
Dim Dump As Range
Set Dump = Sheet3.Range("A:M")
'------------------------------------------------
Dim antkat As Long
antkat = WorksheetFunction.Count(Rgensheet.Range("C:C"))
Dim kat As Range
Set kat = Myworkbook.Sheets("RGenInput").Range("C1:C" & antkat)
Dim kst As Long
kst = 242020
'To make matters easy I try to get the macro work for a single cost centre first...
'I plan to have a For-loop around that covers all of them, with the antkat variable
Dim artnos As Range
Dim artno As Long
Dim n As Integer
n = 1
For Each Row In Dump.Rows
If IsNumeric(Sheet3.Range("M" & Row.Row)) Then
If Sheet3.Range("M" & Row.Row) = kst Then
artno = Cells(Row.Row, 6)
On Error Resume Next
If IsError(Application.Match(artno, artnos, False)) Then
' I used the same code once to create a list of unique values from a huge list but I am unsure wether I can do this to a range that has no dimensions...
Set artnos.Range(1, n).Value = artno
n = n + 1
End If
End If
End If
Next Row
Now - this is ugly and very not up to my code standard but it has been a bigger project than what I normally do.
The question is twofold.
Is it possible to define a range variable that is completely flexible as to dimensions? This is what I am used to, you can just add rows to a variable table in sql like nothing but I am starting to think this is not possible the way I am trying to do it
Is this a reasonable way to execute the plan I made beforehand? If my code is to messy to read or the errors I make too many - can you please help me find a plan of execution or steps that can perform what I need? I can - with the help of google - figure out how to do the steps. That has worked for me in the past... =P
I found the answer, by chance, browsing through some microsoft help files. Who would have thought.
I was mistaken in thinking that a variable range can be used as the array. For future users having issues giving a variable several values - do read up on arrays which are defined by adding closed parentheses to your variable
Dim variable as integer
Dim variablearray() as integer