Excel VBA 'dim as Variant' won't allow 'for each' looping - excel

I'm in a bit of a trap with my code. I'm trying to delete charts that occupy the same merged cell, but I'm getting an error. The code wont compile for each ScrapChart in AllChartsInBox() if scrapchart isn't set as variant, but then I get Run-time error 91 trying to run ScrapChart.delete.
Why Does Scrapchart have to be set as variant, but SheetChart works fine in the For Each SheetChart In Ws_Charts.ChartObjects loop when it's been set as a ChartObject?
option explicit
Dim NumberofChartsinRange, ChartBoxIndex As Long
Dim SheetChart, AllChartsInBox() As ChartObject
Dim ScrapChart As Variant
Set Chartbox = Ws_Charts.Range("A1:F6")
Ws_Charts.Cells(1,1).Formula2 = formulastring
Chartbox.Merge
Chartbox.HorizontalAlignment = xlRight
Chartbox.VerticalAlignment = xlBottom
NumberofChartsinRange = 0
If Ws_Charts.ChartObjects.Count = 0 Then
Else
ReDim AllChartsInBox(Ws_Charts.ChartObjects.Count - 1)
For Each SheetChart In Ws_Charts.ChartObjects
If Not Intersect(SheetChart.TopLeftCell, Chartbox) Is Nothing Then
NumberofChartsinRange = NumberofChartsinRange + 1
Set AllChartsInBox(ChartBoxIndex) = SheetChart: ChartBoxIndex = ChartBoxIndex + 1
End If
Next
End If
If NumberofChartsinRange > 1 Then
For Each ScrapChart In AllChartsInBox
ScrapChart.Delete
Next ScrapChart
End If

You can do this in a single pass through the ChartObjects collection:
Dim SheetChart, co As ChartObject, ChartBox As Range
Dim tmp As ChartObject, foundOne As Boolean, i As Long
Set ChartBox = Ws_charts.Range("A1:F6")
Ws_charts.Cells(1, 1).Formula2 = formulastring
ChartBox.Merge
ChartBox.HorizontalAlignment = xlRight
ChartBox.VerticalAlignment = xlBottom
For i = Ws_charts.ChartObjects.Count To 1 Step -1
Set co = Ws_charts.ChartObjects(i)
If Not Intersect(co.TopLeftCell, ChartBox) Is Nothing Then
If Not foundOne Then 'first chart found?
Set tmp = co
foundOne = True
Else
'multiple charts - delete the first one and this one...
If Not tmp Is Nothing Then tmp.Delete
co.Delete
End If
End If
Next i

Related

Dynamically update the count of selected CheckBox in Excel using VBA

I am trying to find out a way to update the count of the selected checkboxes in excel using VBA.
i.e as the user selects the checkbox, the count has to get updated across the relevant filed. For example, If I select first check box ABC/18-49. The count at the top for (18-49) should get updated to 3.
P.S: This is how I have created the checkboxes dynamically.
Sub Main()
Dim Rng As Range
Dim WorkRng As Range
Dim Ws As Worksheet
On Error Resume Next
Set Ws = ThisWorkbook.Sheets(1)
Ws.Range("A:A").Insert
Set WorkRng = Ws.Range("A2:A" & Ws.UsedRange.Rows.Count)
Application.ScreenUpdating = False
For Each Rng In WorkRng
With Ws.CheckBoxes.Add(Rng.Left, Rng.Top, Rng.Width, Rng.Height)
.Characters.Text = "Yes"
End With
Next
WorkRng.ClearContents
WorkRng.Select
Application.ScreenUpdating = True
End Sub
Try the next way, please:
Copy the next Subs in a standard module and run the first one. It will assign a specific macro to all check boxes from column A:A:
Sub AssingMacro()
Dim sh As Worksheet, s As Shape, chkB As CheckBox
Set sh = ActiveSheet
For Each s In sh.Shapes
If left(s.Name, 6) = "Check " And s.TopLeftCell.Column = 1 Then
s.OnAction = "CheckBoxesHeaven"
End If
Next
End Sub
Sub CheckBoxesHeaven()
Dim sh As Worksheet, chB As CheckBox
Set sh = ActiveSheet
Set chB = sh.CheckBoxes(Application.Caller)
If chB.Value = 1 Then
Debug.Print chB.TopLeftCell.Offset(0, 2).Value
If chB.TopLeftCell.Offset(0, 2).Value = "18-49" Then
sh.Range("C3").Value = sh.Range("C3").Value + 1
ElseIf chB.TopLeftCell.Offset(0, 2).Value = "50-64" Then
sh.Range("C1").Value = sh.Range("C1").Value + 1
Else
sh.Range("C2").Value = sh.Range("C2").Value + 1
End If
Else
If chB.TopLeftCell.Offset(0, 2).Value = "18-49" Then
sh.Range("C3").Value = sh.Range("C3").Value - 1
ElseIf chB.TopLeftCell.Offset(0, 2).Value = "50-64" Then
sh.Range("C1").Value = sh.Range("C1").Value - 1
Else
sh.Range("C2").Value = sh.Range("C2").Value - 1
End If
End If
End Sub
Assort the values in range "C1:C3" to match the appropriate check boxes value. In order to automatically do that, please use the next code:
Sub ResetCheckBoxesValues()
Dim sh As Worksheet, chkB As CheckBox, i As Long
Dim V50_64 As Long, V18_49 As Long, VLess18 As Long
Set sh = ActiveSheet
For Each chkB In sh.CheckBoxes
If chkB.TopLeftCell.Column = 1 Then
Select Case chkB.TopLeftCell.Offset(0, 2).Value
Case "50-64"
If chkB.Value = 1 Then V50_64 = V50_64 + 1
Case "18-49":
If chkB.Value = 1 Then V18_49 = V18_49 + 1
Case "<18":
If chkB.Value = 1 Then VLess18 = VLess18 + 1
End Select
End If
Next
sh.Range("C1:C3").Value = Application.Transpose(Array(V50_64, VLess18, V18_49))
End Sub
Start playing with check boxes selection. It will add a unit to the appropriate cell if checking and decrease it with a unit in case of unchecking.
Please, test it and send some feedback
It will not be "very" dynamic, make sure to click on a random Excel cell, to make the formula recalculate after updating the check on the checkbox.
But the formula works in Excel, with the checkboxes you have created:
Public Function CountCheckBoxes()
Dim chkBox As Shape
Dim counter As Long
With ThisWorkbook.Worksheets(1)
For Each chkBox In .Shapes
If InStr(1, chkBox.Name, "Check Box") Then
If .Shapes(chkBox.Name).OLEFormat.Object.Value = 1 Then
counter = counter + 1
End If
End If
Next chkBox
End With
CountCheckBoxes = counter
End Function
Probably you should think about a suitable workaround to avoid ThisWorkbook.Worksheets(1), depending on where the code is residing.

1004 error when copying and pasting shapes via VBA in Excel

When I try and copy and paste shapes in Excel, I get a debug message telling me there is a
1004 error - Copy Method of Picture Class Failed
When I then press continue in the macro, it works? I tried adding an Application.Wait(5) statement to add a delay in, but the same thing happens. I tried adding DoEvents between the Copy and Paste, but it didn't help.
Public Sub PlotApprovals()
Dim lngRow As Long
Dim lngCol As Long
Dim strCountry As String
Dim datEmergencyUseApproval As Date
Dim rngSyringe As Range
Dim intCountryCols As Integer
Dim intColCount As Integer
Dim shpCopy As Shape
Dim shpPaste As Shape
Dim intShapeIndex As Integer
intCountryCols = 1
intColCount = 4
lngCol = 4
DeleteShapes
For intColCount = 1 To 4
If intColCount = 1 Then
lngCol = 4
ElseIf intColCount = 2 Then
lngCol = 9
ElseIf intColCount = 2 Then
lngCol = 14
ElseIf intColCount = 2 Then
lngCol = 19
End If
For lngRow = 3 To 42
Set rngSyringe = shtDashboard.Cells(lngRow, lngCol + 1)
strCountry = shtDashboard.Cells(lngRow, lngCol)
datEmergencyUseApproval = Application.WorksheetFunction.VLookup(strCountry, shtData.Range("A:X"), 24, False)
If datEmergencyUseApproval <> 0 Then
Set shpCopy = shtDashboard.Shapes("syringeEmergencyUse")
shpCopy.Copy
shtDashboard.Paste
intShapeIndex = idxLastShape("Dashboard")
Set shpCopy = shtDashboard.Shapes(intShapeIndex)
shpCopy.Name = "syringe"
shpCopy.Left = rngSyringe.Left
shpCopy.Top = rngSyringe.Top
End If
Next lngRow
Next intColCount
End Sub
Public Sub DeleteShapes()
Dim shp As Shape
For Each shp In ActiveSheet.Shapes
If shp.Name = "syringe" Then
shp.Delete
End If
Next shp
End Sub
Function idxLastShape(shtName As String) As Long
Dim sh As Shape
For Each sh In Sheets(shtName).Shapes
idxLastShape = idxLastShape + 1
Next sh
End Function
----------UPDATE-------------
If the main copy and paste logic is updated as below, I now get a Copy of Object Shape failed error. It takes me into Debug, where if I proceed it works. So the failure is at runtime, but it works in debug mode when I step through.
Set shpCopy = shtDashboard.Shapes("syringeEmergencyUse")
shpCopy.Select
shpCopy.Copy
rngSyringe.Select
shtDashboard.Paste
intShapeIndex = idxLastShape("Dashboard")
Set shpCopy = shtDashboard.Shapes(intShapeIndex)
shpCopy.Name = "syringe"
shpCopy.Left = rngSyringe.Left
shpCopy.Top = rngSyringe.Top
GreenCell rngCountry
The issue appears when you shtDashboard.Paste and there is a shape selected and not a cell. Make sure you select a cell before pasting:
shpCopy.Select
shpCopy.Copy
shtDashboard.Range("A1").Select 'select a cell to ensure no shape is selected
shtDashboard.Paste
The solution it seems is to add this after the copy, must be a timing issue:
shp.Copy
Application.Wait(Now+TimeSerial(0,0,2))
DoEvents
rngSyringe.Select
ActiveSheet.Paste

Conditionally hiding columns

I am trying to hide columns (Z,AA,AB,AC) if one of dependent cells are blank. i.e. if Range1 is blank entire column Z is hidden, Range2 is blank then entire column AA is hidden etc.
I know I could implement simple If Else/ .EntireColumn.Hidden statment but I was thinking to use code like below to make it neater. Any suggestions how to make it work ?
Sub(test)
Dim cell As Variant
Dim i As Integer
Dim MyArray(1 To 4) As Range
With ThisWorkbook.Worksheets("ReturnedHoldMail")
Set MyArray(1) = Sheets("test1").Range("Range1")
Set MyArray(2) = Sheets("test1").Range("Range2")
Set MyArray(3) = Sheets("test1").Range("Range3")
Set MyArray(4) = Sheets("test1").Range("range4")
For i = LBound(MyArray) To UBound(MyArray)
On Error Resume Next
For Each cell In MyArray(i)
If Len(cell.Value) < 1 Then
cell.EntireColumn.Hidden = True
Else
cell.EntireColumn.Hidden = False
End If
Next
Next
End With
End Sub
If you want the ranges that are hidden to be independent of the ranges being tested for emptiness, try the following:
Sub test()
Dim cell As Range
Dim i As Integer
Dim MyArray(1 To 4) As Range
Dim HideArray(1 To 4) As Range
Dim will_hide As Boolean
Set MyArray(1) = Sheets("test1").Range("Range1")
Set MyArray(2) = Sheets("test1").Range("Range2")
Set MyArray(3) = Sheets("test1").Range("Range3")
Set MyArray(4) = Sheets("test1").Range("Range4")
Set HideArray(1) = Sheets("test1").Range("Range5") ' or eg. Sheets("test2").Range("Z:Z")
Set HideArray(2) = Sheets("test1").Range("Range6")
Set HideArray(3) = Sheets("test1").Range("Range7")
Set HideArray(4) = Sheets("test1").Range("Range8")
For i = LBound(MyArray) To UBound(MyArray)
will_hide = True
For Each cell In MyArray(i)
If Len(cell.Value) > 0 Then
will_hide = False
End If
Next
HideArray(i).EntireColumn.Hidden = will_hide
Next
End Sub

Remove a leading space from a range

I have a column range of about 500 rows. Most of those cells are stored as text. I populate a listbox on a userform with the values from that range. When a user selects one of those values from the listbox an event will find the value on the same row from another column using Index and Match and display it in a label on the userform. I get an error when selecting one of the few cells in the listbox that are not stored as text in the range because there is a leading space. I am assuming that the populated listbox automatically removes leading spaces from any cells in the range. Therefore, when it tries to find value 12345 from the listbox, for example, in the range it can't find it because the range contains (space)12345. I have tried:
Public Sub UserForm_Initialize()
Dim arr() As Variant
Dim rNum As Range
Const sNum As String = "Number"
Me.EnableEvents = False
wsName = "Report"
Set curWb = ActiveWorkbook
Set pReport = curWb.Worksheets(wsName)
Set pTable = pReport.ListObjects("tableName")
With pReport
If .AutoFilterMode = True Then .ShowAllData
.Cells.Rows.Hidden = False
.Cells.Columns.Hidden = False
End With
Set wf = Application.WorksheetFunction
With pTable
Set rNum = .ListColumns(.ListColumns(sNum).Range.column).DataBodyRange
End With
-- HERE is where I tried all my implementations without success
arr = wf.Transpose(pReport.Range(rNum.address).Value)
Call BubbleSort(arr)
frmIssues.lstIssues1.List = arr
lstIssues1.ListStyle = 1
lstIssues2.ListStyle = 1
lstIssues1.MultiSelect = 2
lstIssues2.MultiSelect = 2
txtFocus.SetFocus
Me.EnableEvents = True
End Sub
Private Sub lstIssues1_Change()
Dim rNum As Range
Dim rTitle As Range
Dim strResult As String
Dim intIndex As Integer
Dim intCount As Integer
Const sNum As String = "Number"
Const sTitle As String = "Title"
If EnableEvents = False Then Exit Sub
With lstIssues1
For intIndex = 0 To .ListCount - 1
If .Selected(intIndex) Then intCount = intCount + 1
Next
End With
If intCount = 1 Then
Set wf = Application.WorksheetFunction
wsName = "Report"
Set curWb = ActiveWorkbook
Set pReport = curWb.Worksheets(wsName)
Set pTable = pReport.ListObjects("tableName")
With pTable
Set rNum = .ListColumns(.ListColumns(sNum).Range.column).DataBodyRange
Set rTitle = .ListColumns(.ListColumns(sTitle).Range.column).DataBodyRange
End With
With pReport
strResult = wf.Index(.Range(rTitle.address), wf.Match(lstIssues1.List(lstIssues1.ListIndex), .Range(rNum.address), 0))
End With
lblDescription.Caption = wf.Trim(strResult)
txtFocus.SetFocus
Else
lblDescription.Caption = ""
txtFocus.SetFocus
Exit Sub
End If
Me.EnableEvents = False
For i = 0 To lstIssues2.ListCount - 1
If lstIssues2.Selected(i) = True Then lstIssues2.Selected(i) = False
Next
Me.EnableEvents = True
End Sub
and numerous variations of it (Clean, CStr, .Text, etc.) and nothing works. Truly, I have no clue how to fix this and any help whatsoever is much appreciated. Thank you!
Clarification
1) This Excel file is generated from the Web.
2) A Macro turns the Worksheet into a table
3) Left(Range("D362"),1) returns 1 (The number, say, is 12345)
4) Before the error occurs Range("D362") returns (space)12345
5) After the error occurs Range("D362") returns (space)12345
I have just tested this and it works in removing the space at the begining of a string. Sadly it isnt a single line as I (and likely you) would have prefered
Sub test()
Dim CellValue As String
Dim lngNumberOfCharacters As Long
CellValue = ActiveCell.Value
CellValueCheck = Left(CellValue, 1)
If CellValueCheck = " " Then
lngNumberOfCharacters = Len(CellValue) - 1
CellValue = Right(CellValue, lngNumberOfCharacters)
ActiveCell.Value = CellValue
End If
End Sub
Let me know if you need anything confirmed

type mismatch 13 in excel 2010

The following code worked perfectly under excel 2003, but in 2010 returns error 'type mismatch 13' in the following line "If Array2(1, i) <> 0 Then"
Anyone has any ideas how to solve this ?
Thx in advance
Sonny
Her is the code:
Sub BerekenGepresteerdeUrenVoorEenMaand(SheetNaam As String)
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Dim Array1 As Variant
Dim Array2 As Variant
Dim Range1 As Range
Dim Range2 As Range
Dim RangeTarget1 As Range
Dim RangeTarget2 As Range
Dim mRange As Excel.Range
Dim RangeNieuwSaldo As Range
Dim i As Integer
Dim j As Integer
Dim k As Integer
Dim l As Integer
Dim subTotaal As Double
ActiveWorkbook.Worksheets(SheetNaam).Activate
Set Range1 = ActiveSheet.Range("EersteRij")
Set Range2 = ActiveSheet.Range("LaatsteRij")
Set RangeTarget1 = ActiveSheet.Range("NaamVeld")
Set RangeTarget2 = ActiveSheet.Range("SaldiVeld")
Array1 = Range1.Value
Array2 = Range2.Value
RangeTarget1.Locked = False
RangeTarget2.Locked = False
j = 0
For i = LBound(Array1, 2) To UBound(Array1, 2)
If Array2(1, i) <> 0 Then 'Line generating error
j = j + 1
RangeTarget1.Cells(j, 1).Value = Array1(1, i)
RangeTarget2.Cells(j, 1).Value = Array2(1, i)
Else
End If
Next
For k = j + 1 To 11
RangeTarget1.Cells(k, 1).Value = ""
RangeTarget2.Cells(k, 1).Value = ""
Next
RangeTarget1.Locked = False
RangeTarget2.Locked = False
Erase Array1
Erase Array2
Set Range1 = Nothing
Set Range2 = Nothing
Set RangeTarget1 = Nothing
Set RangeTarget2 = Nothing
Application.EnableEvents = True
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub
i think , at some time , i gets bigger than the input data in array2...
like no data stored in array2(1,10000) or so, and nothing is not a number (like <>0)
so maybe u need a fail-proof condition before your faulty line like:
if not array2(1,i) is nothing then 'or you might just want to exit the For loop here.
if array2(1,i)<>0 then ...
'if this doesn't work try if not IsEmpty(array2(1,i)) as condition
try it, i can't tell more without seing the actual data here...
read more about ubound maybe too, its the upper limit of your array, being data in it or not.
I once thought too that it is the last entry of data in my array, but no, in fact.
dim test(20) as integer
test(1)=23
..
test(10)=44 'last input
a=ubound(test) 'my guess it will return 20, and not 10

Resources