VBA method 'range of object' _Worksheet failed Shapes.Range(Array - vba

I am trying to move shapes on the 2nd sheet based on the values of the 1st sheet. I keep getting an error with the line....Shapes.Range(Array(.... below is the code.
Sub graphics_mover()
' graphics_mover Macro
Dim SWL_row As Double, PWL_row As Double
Dim rng As Variant, i As Integer, colNum As Integer, Data As Worksheet, Pict As Worksheet
Set Data = ThisWorkbook.Worksheets(1)
'Set Pict = ThisWorkbook.Worksheets(2)
Set Pict = Workbooks("Well Pictographs2.xlsm").Worksheets(2)
i = 1
For i = 1 To 27
SWL_row = Data.Cells(2, i + 1).Value
SWL_row = Int(SWL_row / 50 + 1)
Pict.Shapes.Range(Array("Isosceles Triangle " & i)).Select
Selection.Top = SWL_row * 15 + 4
PWL_row = Data.Cells(3, i + 1).Value
PWL_row = Int(PWL_row / 50 + 1)
Pict.Shapes.Range(Array("Freeform " & i)).Select
Selection.Top = PWL_row * 15 + 1
i = i + 1
Next i
'--------------------------
End Sub
the line that is causing the error is:
Pict.Shapes.Range(Array("Freeform " & i)).Select
I appreciate any solutions.

I'm curious as to what the value of i is when you crash. The code is largely the same as a recorded macro but the syntax is correct if the named shape(s) exist.
First run this small snippet to output all of the shapes' names to the VBE's Immediate Window (Ctrl+G).
Sub List_Shapes()
Dim i As Long
With Workbooks("Well Pictographs2.xlsm").Worksheets(2)
For i = 1 To .Shapes.Count
Debug.Print .Shapes(i).Name
Next i
End With
End Sub
When you are in the VBE, tap Ctrl+G to open the Immediate Window and check the output. Make sure you have Isosceles Triangle 1 through Isosceles Triangle 27 (inclusive).
Next run through this modification of your macro.
Sub graphics_mover()
Dim SWL_row As Double, PWL_row As Double
Dim rng As Variant, i As Integer, colNum As Integer, Data As Worksheet, Pict As Worksheet
On Error Resume Next
Set Data = ThisWorkbook.Worksheets(1)
With Workbooks("Well Pictographs2.xlsm").Worksheets(2)
For i = 1 To 27
SWL_row = Data.Cells(2, i + 1).Value
SWL_row = Int(SWL_row / 50 + 1)
If Not .Shapes("Isosceles Triangle " & i) Is Nothing Then
.Shapes("Isosceles Triangle " & i).Top = SWL_row * 15 + 4
Debug.Print "moved " & .Shapes("Isosceles Triangle " & i).Name
End If
PWL_row = Data.Cells(3, i + 1).Value
PWL_row = Int(PWL_row / 50 + 1)
If Not .Shapes("Freeform " & i) Is Nothing Then
.Shapes("Freeform " & i).Top = PWL_row * 15 + 1
Debug.Print "moved " & .Shapes("Freeform " & i).Name
End If
Next i
End With
End Sub
I'm not a big fan of using On Error Resume Next but you are dealing with an object that is avoiding detection. The VBE's Immediate window will report the shapes that it could move.

Related

Chart vba suddenly getting error 1004?

I wrote a piece of VBA code that was working before, but it gets error 1004 on name/xvalue/value recently. I am using excel 2010.
Sub LineChartTemp()
Dim i As Integer, j As Integer, k As Integer
' i = series, j = start row, k = end row
ActiveSheet.Shapes.AddChart.Select
ActiveChart.ChartType = xlLine
Dim chart As chart
Set chart = ActiveChart
For i = 1 To 156
j = (i - 1) * 13 + 1 + 1
k = j + 12
' two 1, one for name row, one for the minus 1, 13 is number of data points of each series
chart.SeriesCollection.NewSeries
chart.SeriesCollection(i).Name = "=" & ActiveSheet.Name & "!$A$" & j & ":$C$" & j
chart.SeriesCollection(i).XValues = "=" & ActiveSheet.Name & "!$D$" & j & ":$D$" & k
chart.SeriesCollection(i).Values = "=" & ActiveSheet.Name & "!$E$" & j & ":$E$" & k
Next i
End Sub

VBA autofilling multidimensional arrays

As a beginner, I would like to ask if it is possible in VBA to autofill formulas in a multidimensional array.
Ι thought and wrote this code and it works with values but not with formulas.
I think that what I am trying to do is very ambitious for my skills
Sub eucldiist()
Dim e(10,10) As Double, i As Integer, j As Integer
For i = 1 To 10
For j = 1 To 10
e(i, j).FormulaArray = "=sqrt((offset('Data1'!$Q$14,$BD$5(offset(i)) -
offset('Data1'!$Q$14,$BD$5(offset(j))^2+ ((offset('Data1'!$U$14,
$BD$5(offset(i))-OFFSET('Data1'!$U$14,$BD$5(offset(j)))^2)"
Next j
Next i
Sheets("Calculations").Select: Range("A20").Select
For i = 1 To 10
For j = 1 To 10
ActiveCell.Value = e(i, j)
ActiveCell.Offset(0, 1).Select
Next j
ActiveCell.Offset(1, -10).Select
Next i
End Sub
Is it possible what I am trying to do?
check this out. put some formulas in a20:j29 before hand
Option Explicit
Sub test()
Dim aaa As Variant
aaa = Range("a20").Resize(10, 10).Formula
Stop ' now examine aaa in "locals" window
' maybe all you want is this
range("a20").Resize(10,10).FormulaArray = "=SQRT((OFFSET(DATA1!Q14,BD5,0)-OFFSET(DATA1!Q14,BD7,0))^2+((OFFSET(DATA1!U14,BD5,0)-OFFSET(DATA1!U14,BD7,0))^2))"
End Sub
i think that this is what you want
NOTE: formula uses absolute addressing, so a column or row insert will break it
delete $ from formula to make it use relative addressing
Sub eucldiist()
Dim base As Range
Set base = Sheets("Calculations").Range("A20")
' Set base = ActiveSheet.Range("A20")
Dim formula As String
Dim i As Integer, j As Integer
For i = 0 To 9 ' rows
For j = 0 To 9 ' columns
formula = "=sqrt(" _
& " (offset('Data1'!$Q$14,$BD$" & 5 + i & ",0) - offset('Data1'!$Q$14,$BD$" & 7 + j & ",0))^2" _
& " + (offset('Data1'!$U$14,$BD$" & 5 + i & ",0) - offset('Data1'!$U$14,$BD$" & 7 + j & ",0))^2" _
& ")"
' Debug.Print formula
base.Offset(i, j) = formula
Next j
Next i
End Sub

#Name? error in cells with VBA code

I am running a MonteCarlo Simulation in Excel with VBA but I only receive #Name? errors in the respective cells. When I click into one of these cells, press F2 and then Return the error disappears and the value is properly calculated. What is wrong here?
This is the code line calculating the respective value:
ActiveCell.Formula = "=Start_Rate * EXP(NORM.S.INV(RAND())* Standard_Deviation * (" & i & " ^1/2)) "
And that is the entire code (if necessary):
Sub MC_Simulation()
Dim i As Integer
Dim k As Integer
Dim StartCell As Range
Dim start_row As Integer
Dim start_column As Integer
iterations = Worksheets("Run_MC").Range("MC_Simulations").Value
Duration = Worksheets("Run_MC").Range("Duration").Value
Mean = Worksheets("Run_MC").Range("Mean").Value
Start_Rate = Worksheets("Run_MC").Range("Start_Rate").Value
Standard_Deviation = Worksheets("Run_MC").Range("Standard_Deviation").Value
start_row = 15
start_column = 1
For i = 1 To Duration
For k = 1 To iterations
Worksheets("Run_MC").Cells(start_row, start_column + i).Select
Selection.Value = i
Worksheets("Run_MC").Cells(start_row + k, start_column).Select
Selection.Value = k
Worksheets("Run_MC").Cells(start_row + k, start_column + i).Select
ActiveCell.Formula = "=Start_Rate * EXP(NORM.S.INV(RAND())* Standard_Deviation * (" & i & " ^1/2)) "
'Selection.Value
Next k
Next i
End Sub
You need to take the VBA variables out of the quotations:
ActiveCell.Formula = "=" & Start_Rate & "*EXP(NORM.S.INV(RAND())*" & Standard_Deviation & "*(" & i & "^1/2))"

Excel VBA: Split to Multiple Sheets

I'm creating a UserForm that allows the user to select a sheet to perform the macro on and enter in X amount of rows in which the ultimate goal is to split the selected sheet into multiple sheets by X amount of rows.
Code:
Dim rowCount As Long
Dim rowEntered As Long
Dim doMath As Long
rowCount = Sheets(Me.ComboBox1.Value).Cells(Rows.Count, "A").End(xlUp).Row 'Count Number of Rows in selected Sheet
rowEntered = Val(Me.TextBox1.Value) 'User enters X amount
If rowCount < rowEntered Then
MsgBox "Enter in another number"
Else
doMath = (rowCount / rowEntered)
For i = 1 to doMath
Sheets.Add.name = "New-" & i
Next i
'Help!!
For i= 1 to doMath
Sheets("New-" & i).Rows("1:" & rowEntered).Value = Sheets(Me.ComboBox1.Value).Rows("1:" & rowEntered).Value
Next i
End If
The last section of code is where I need help because I can't seem to figure out how to do it properly..
The code currently loops through the newly added sheets and "pastes" in the same rows. For example, if the sheet selected has 1000 rows (rowCount), and rowEntered is 500, then it would create 2 new sheets. Rows 1-500 should go in New-1 and Rows 501-1000 should go into New-2. How can I achieve this?
Check below code. Please, read comments.
Option Explicit
'this procedure fires up with button click
Sub Button1_Click()
SplitDataToSheets Me.ComboBox1.Value, CInt(Me.TextBox1.Value)
End Sub
'this is main procedure
Sub SplitDataToSheets(ByVal shName As String, ByVal rowAmount As Long)
Dim srcWsh As Worksheet, dstWsh As Worksheet
Dim rowCount As Long, sheetsToCreate As Long
Dim i As Integer, j As Long
'handle events
On Error GoTo Err_SplitDataToSheets
'define source worksheet
Set srcWsh = ThisWorkbook.Worksheets(shName)
'Count Number of Rows in selected Sheet
rowCount = srcWsh.Range("A" & srcWsh.Rows.Count).End(xlUp).Row
'calculate the number of sheets to create
sheetsToCreate = CInt(rowCount / rowAmount) + IIf(rowCount Mod rowAmount > 0, 1, 0)
If rowCount < rowAmount Then
If MsgBox("The number of rows in source sheet is less then number of " & vbCr & vbCr & _
"The rest of message", vbQuestion + vbYesNo + vbDefaultButton2, "Question..") = vbYes Then GoTo Exit_SplitDataToSheets
End If
'
j = 0
'create the number of sheets in a loop
For i = 1 To sheetsToCreate
'check if sheet exists
If SheetExists(ThisWorkbook, "New-" & i) Then
'clear entire sheet
Set dstWsh = ThisWorkbook.Worksheets("New-" & i)
dstWsh.Cells.Delete Shift:=xlShiftUp
Else
'add new sheet
ThisWorkbook.Worksheets.Add After:=ThisWorkbook.Worksheets(ThisWorkbook.Worksheets.Count)
Set dstWsh = ActiveSheet
dstWsh.Name = "New-" & i
End If
'copy data
srcWsh.Range("A" & j + 1 & ":A" & j + rowAmount).EntireRow.Copy dstWsh.Range("A1")
'increase a "counter"
j = j + rowAmount
Next i
'exit sub-procedure
Exit_SplitDataToSheets:
On Error Resume Next
Set srcWsh = Nothing
Set dstWsh = Nothing
Exit Sub
'error sub-procedure
Err_SplitDataToSheets:
MsgBox Err.Description, vbExclamation, Err.Number
Resume Exit_SplitDataToSheets
End Sub
'function to check if sheet exists
Function SheetExists(ByVal wbk As Workbook, ByVal wshName As String) As Boolean
Dim bRetVal As Boolean
Dim wsh As Worksheet
On Error Resume Next
Set wsh = wbk.Worksheets(wshName)
bRetVal = (Err.Number = 0)
If bRetVal Then Err.Clear
SheetExists = bRetVal
End Function
Try!
Modify that problematic code snippet as shown below:
For i = 1 To doMath
Sheets("New-" & i).Range("1:" & rowEntered).Value = Sheets(Me.ComboBox1.Value).Range((i - 1) * rowEntered + 1 & ":" & i * rowEntered).Value
Next i
Also modify the following line to calculate the "Ceiling" value:
doMath = Fix(rowCount / rowEntered) + IIf(rowCount Mod rowEntered > 0, 1, 0)
The simulated VBA "Ceiling" function used to calculate the doMath value could be also written as:
doMath = Int(RowCount / rowEntered) + Abs(RowCount Mod rowEntered > 0)
Note: In this particular sample, you can use VBA INT and FIX functions interchangeably.
Hope this will help.

How to define dynamically changing column number into a formula in VBA?

I have a VBA code that calculates a formula (I know it's pretty long):
Cells(i, mcol) = "=IF(RC[-1]=""C"",(RC[-3]/SUMIFS(C[-3],C66,RC66))*(VLOOKUP('Sheet1'!RC66,GA_C!C1:C4,4,0)),SUM((RC[-3]/SUMIFS(C[-3],C66,RC66))*(VLOOKUP('Sheet1'!RC66,GA_C!C1:C4,4,0)),(RC[-3]/SUMIFS(C[-3],C66,RC66,C[-1],""GA + C""))*(VLOOKUP('Sheet1'!RC66,GA_C!C1:C3,3,0))))"
in the Vlookup it takes a 4th column in the range from C1:C4 and the 3rd column from the range C1:C3.
It was ok till the column number (4 and 3) was fixed.
Now it changes each time running For cycle.
Foe example, the second run column numbers will be 5 and 4, the third run 6 and 5 and so on till 12.
Is there any way to integrate the column number changed dynamically into the formula above?
Thanks a lot!
I put also a whole code as well.
Sub AutoCalcV2()
Dim ws As Worksheet
Dim LastRow As Long
Dim i As Integer, n As Integer, x As Integer, j As Integer, mcol As Integer
Set ws = ActiveWorkbook.Sheets("Sheet1")
ws.Select
LastRow = Sheets("Sheet1").Range("A" & Sheets("Sheet1").Rows.Count).End(xlUp).Row
mcol = 71
For j = 1 To 11
mcol = mcol + 1
For i = 3 To LastRow
On Error Resume Next
Cells(i, mcol) = "=IF(RC[-1]=""C"",(RC[-3]/SUMIFS(C[-3],C66,RC66))*(VLOOKUP('Sheet1'!RC66,GA_C!C1:C4,4,0)),SUM((RC[-3]/SUMIFS(C[-3],C66,RC66))*(VLOOKUP('Sheet1'!RC66,GA_C!C1:C4,4,0)),(RC[-3]/SUMIFS(C[-3],C66,RC66,C[-1],""GA + C""))*(VLOOKUP('Sheet1'!RC66,GA_C!C1:C3,3,0))))"
Range("BT4").Select
Next i
Next j
End Sub
Dim iColumn as Integer
mcol = 71
For j = 1 To 11
iColumn = 4
mcol = mcol + 1
For i = 3 To LastRow
On Error Resume Next
Cells(i, mcol) = "=IF(RC[-1]=""C"",(RC[-3]/SUMIFS(C[-3],C66,RC66))*(VLOOKUP('Sheet1'!RC66,GA_C!C1:C4," & str(iColumn) & ",0)),SUM((RC[-3]/SUMIFS(C[-3],C66,RC66))*(VLOOKUP('Sheet1'!RC66,GA_C!C1:C4," & str(iColumn) & ",0)),(RC[-3]/SUMIFS(C[-3],C66,RC66,C[-1],""GA + C""))*(VLOOKUP('Sheet1'!RC66,GA_C!C1:C3,3,0))))"
Range("BT4").Select
iColumn = iColumn + 1
Next i
Next j
So based on what I understood, you have 3 vlookups and you want to use 4 (4+1,5+1,6+1) for first Two vlookups and 3 (3+1,4+1,5+1) for third one.
If that so, here how you can increment your 4 and 3.
Sub AutoCalcV2()
Dim ws As Worksheet
Dim LastRow As Long
Dim i, n, x, j, mcol, iCol As Integer '<-- Changed here
Set ws = ActiveWorkbook.Sheets("Sheet1")
ws.Select
LastRow = Sheets("Sheet1").Range("A" & Sheets("Sheet1").Rows.Count).End(xlUp).Row
mcol = 71
iCol = 4 '<-- Newly added
For j = 1 To 11
mcol = mcol + 1
For i = 3 To LastRow
On Error Resume Next
'Changed the formula
Cells(i, mcol) = "=IF(RC[-1]=""C"",(RC[-3]/SUMIFS(C[-3],C66,RC66))" & _
"*(VLOOKUP('Sheet1'!RC66,GA_C!C1:C4," & iCol & ",0)),SUM((RC[-3]/SUMIFS(C[-3],C66,RC66))" & _
"*(VLOOKUP('Sheet1'!RC66,GA_C!C1:C4," & iCol & ",0)),(RC[-3]/SUMIFS(C[-3],C66,RC66,C[-1],""GA + C""))" & _
"*(VLOOKUP('Sheet1'!RC66,GA_C!C1:C3," & i & ",0))))"
Range("BT4").Select
iCol = iCol + 1
Next i
Next j
End Sub
OK, Take a look. I can give an suggestion for you. Not the whole formula, Just a part of VLOOKUP.
I know that this is your formula for cell in loop:
Cells(i, mcol) = "=IF(RC[-1]=""C"",(RC[-3]/SUMIFS(C[-3],C66,RC66))*(VLOOKUP('Sheet1'!RC66,GA_C!C1:C4,4,0)),SUM((RC[-3]/SUMIFS(C[-3],C66,RC66))*(VLOOKUP('Sheet1'!RC66,GA_C!C1:C4,4,0)),(RC[-3]/SUMIFS(C[-3],C66,RC66,C[-1],""GA + C""))*(VLOOKUP('Sheet1'!RC66,GA_C!C1:C3,3,0))))"
Now is you want to change the dynamically the column according to looping. I understand the column pair as follow:
C1:C4 & C1:C3
C1:C5 & C1:C4
C1:C6 & C1:C5
C1:C7 & C1:C6
C1:C8 & C1:C7
C1:C9 & C1:C8
C1:C10 & C1:C9
C1:C11 & C1:C10
C1:C12 & C1:C11
Actually, your looping are not clear, I can't use it. So, I used as follow:
For column = 3 To 11
mcol = mcol + 1
For row = 1 To lastRow
Cells(row , mcol) = "=IF(RC[-1]=""C"",(RC[-3]/SUMIFS(C[-3],C66,RC66))*" & _
"(VLOOKUP('Sheet1'!RC66,GA_C!C1:C" & column + 1 & "," & column + 1 & ",0))" & _
",SUM((RC[-3]/SUMIFS(C[-3],C66,RC66))*" & _
"(VLOOKUP('Sheet1'!RC66,GA_C!C1:C" & column + 1 & "," & column + 1 & ",0))" & _
",(RC[-3]/SUMIFS(C[-3],C66,RC66,C[-1],""GA + C""))*" & _
"(VLOOKUP('Sheet1'!RC66,GA_C!C1:C" & column & "," & column & ",0))))"
Next row
Next column
Try as above, it will be helpful for you.