I have some code referencing Slicers:
For Each item In wb.SlicerCaches("Segment").SlicerItems
If item.Selected = True Then
If Len(sSegment) > 0 Then sSegment = sSegment & "|"
sSegment = sSegment & item.Caption
End If
Next item
but I get Invalid procedure call or argument. I've seen many examples referencing them by name, but can't get it to work. If I use (1), (3) etc and then add a slicer, it messes up the order, so the code is mucked up.
How can I reference them by name, my end goal is to iterate through selected items.
You may need to reference the slicercache by adding Slicer_ in front of it.
For example, I added an Authors slicer to a table containing information about books and I could reference it by using this code:
Debug.Print ActiveWorkbook.SlicerCaches("Slicer_Author").Slicers("Author").Caption
The reason I knew to add Slicer_ is because I right clicked the slicer and then selected Slicer Settings... and saw this:
And that seems to reference the slicer fine. It was really dumb luck that I happened to see that and thought to try it.
Try:
For Each item In wb.SlicerCaches.Item("Segment").SlicerItems
Related
I have a list box that I'm trying to populate in an application to contain Excel tab names or Access tables. It's created by a simple schema grab:
dtSheet = OpenCon.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, New Object() {Nothing, Nothing, Nothing, "TABLE"})
It then gets put into a simple list (of String):
For Each Row In dtSheet.Rows
ListOfSheets.Add(Row("TABLE_NAME").ToString())
Next
This works fine if I open up an Access database, the names of the tables are listed nicely. However, when I use it for Excel, I get symbols such as $ and quotes "'". I'd like to trim this off to just have the tab names but so far I haven't been able to find anything to help my issue specifically.
My suspicion is that the answer is in the {Nothing...."TABLE"} object. I'm a little light on how filters like this work and I was having issues wrapping my head around it after reading the .NET documentation.
Another idea would be to do some post string alteration trimming but I'd like to see if there was an easier way to get the simple string name that I want from the start.
Any help would be appreciated.
Based on the discussion from jmcihinney, I built a slightly better code.
dtSheet = OpenCon.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, New Object() {Nothing, Nothing, Nothing, "TABLE"})
dtSheet.Columns.Add("Table_Text", Type.GetType("System.String"))
For i As Integer = dtSheet.Rows.Count - 1 To 0 Step -1
If Microsoft.VisualBasic.Strings.Right(dtSheet.Rows(i)("TABLE_NAME"), 1) <> "$" Then
dtSheet.Rows.RemoveAt(i)
Else
dtSheet.Rows(i)("TABLE_Text") = Replace(dtSheet.Rows(i)("TABLE_NAME"), "$", "")
End If
Next
I essentially add a column to the datatable that is built from the list pull. To remove anything that isn't a table (e.g. named ranges, Sheet views) I check the Table_Name column for the suffix of "$". Note I go backwards to keep from messing with any indexing.
Then in the Else statement I put a "Replace" to make the table_text a "$"less version of Table_Name
That way I can then build my listbox like this:
Me.lbTableList.DataSource = dtsheet
Me.lbTableList.DisplayMember = "TABLE_Text"
Me.lbTableList.ValueMember = "TABLE_NAME"
This makes my table look nice regardless if I loaded an Access database or Excel file. This also allows me to just pass the TABLE_NAME to the connection command and not worry whether there is a "$" in the name or not:
DBCmd.CommandText = "SELECT * FROM [" & strTable & "]"
I am trying to hide and unhide series in a chart based on their name using excel vba and I have a error 1004 invalid parameter after the first run of the for cycle.
Sub macroChart3()
'
' macroChart3 Macro test
'
Dim i, n As Integer
For i = 1 To 96 Step 1
If ActiveChart.SeriesCollection(i).Name = "*contracted*" Then
ActiveChart.SeriesCollection(i).IsFiltered = False
Else
ActiveChart.SeriesCollection(i).IsFiltered = True
End If
Next i
End Sub
SeriesCollection.IsFiltered method seemed to toggle this check box:
I couldn't use that. I wanted to record macro and see if any other method is used but the checkbox is gone in 2010:
So it might be not possible to use that anymore. If you are using a different version where this method exists you might have a problem that the series is not listed in in seriesCollection anymore:
Remarks from MSDN
When a user filters out a series, the series IsFiltered property switches to True, and the series is transferred out of its parent SeriesCollection.
See if you can use FullSeriesCollection instead when you change the visibility of series:
ActiveChart.FullSeriesCollection(2).IsFiltered = True
If that doesn't work you might add and remove ranges instead of hiding them.
UPDATE:
Run your macro in step mode (F8) so you have full visibility of the execution steps. Add your evaluated expressions (ones that are used within IFs) to see their result and you will find out if they are incorrect or are evaluated as FALSE and try to figure out why.
And don't forget to up vote the answer if you find it helpful.
thanks for the quick reply, the error is fixed, but still not all the series are processed by the if clauses in the for cycle, for example this statement:
Else
ActiveChart.SeriesCollection(i).IsFiltered = True
End If
Isn't executed and I don't understand why.
The problem I have is that the user is copying from one content control and pasting it into another accidentally. When extracting the data from this form, it then picks up that extra CC and therefore the value twice over.
When pulling the data I'm trying to see if a CC has a ParentCC and then delete it, but I keep getting
Run time error 5825: Object has been deleted.
I can understand why but I'm unsure as to how get around it, nothing I've searched seems to work.
'With Word document Statement precedes this
For Each CCtrl In .ContentControls
CCtrlText = CCtrl.Range.Text
If Not CCtrl.ParentContentControl Is Nothing Then
CCtrl.ParentContentControl.Range.Text = CCtrlText
CCtrl.Delete
End If
Next
How can I remove this content control which is duplicated inside the other and retain the input information?
So after some messing around and looking into how the local variables properties changed as a stepped through the code I have found that the line:
CCtrl.ParentContentControl.Range.Text = CCtrlText
Was in effect replacing the Content Control (CC) in it's ParentCC range property with the input text, and therefore deleting the duplicated CC.
CCtrl.Delete was trying to delete an object that had already been deleted and that swhy it was throwing an error.
I think with a foreach loop you can't alter the contents of the list/array without impacting the function of the loop. If you instead use the indexers, it should allow you to alter the collection, since you are not impacting the loop (number to number):
Dim i As Integer
Dim c As ContentControl
For i = 1 To d.ContentControls.Count
Set c = d.ContentControls(i)
c.Delete
Next i
I'm having a small issue manipulating data.
I have a few check-boxes to select various items on the screen, which in turn inputs relevant data such as item name, price, etc. The issue is that these names have to go onto a invoice, and I cannot get the names to transfer onto the invoice nicely.
The invoice has to record the items, but it needs to check to see if a item has been already applied to the invoice and this is what I'm having problems with.
How can I get items to collectively display on a sheet without any additional interactions (I just click the relevant checkbox instead of manually typing it in), and display them nicely.
The items 'Underlay and Extended Warranty' need to be displayed one after another, and not 2-3 boxes away.
Example:
Underlay Extended Warranty
I don't want this:
Underlay
Extended Warranty
Is there a solution to this?
Update:
This happens if I do it the way I know:
I solved this by making a custom Excel VBA Macro that basically tells us the cell that is free which is closest to the top of the invoice:
Public Function GetApplicableCell() As String
Range("C20").Select
If (IsEmpty(Range("'Invoice Sheet'!C20").Value)) Then
GetApplicableCell = "C20"
End If
If (IsEmpty(Range("'Invoice Sheet'!C21").Value)) Then
GetApplicableCell = "C21"
End If
If (IsEmpty(Range("'Invoice Sheet'!C22").Value)) Then
GetApplicableCell = "C22"
End If
If (IsEmpty(Range("'Invoice Sheet'!C23").Value)) Then
GetApplicableCell = "C23"
End If
If (IsEmpty(Range("'Invoice Sheet'!C24").Value)) Then
GetApplicableCell = "C24"
End If
End Function
It can be called by a =GetApplicableCell() from within the worksheet, and we can work with this to produce a workable solution.
I have a VBA procedure (in Excel 2007) where I aspire to set the ListFillRange property of a combobox styled as a list using an array.
I know this works if I right click the combobox and write "Sheet1!$F2:$F17" next to the "ListFillRange" property. I can also do this in code. However, I am interested in dynamically setting the value of this property by assigning it an array.
I know for sure the array works as I tested it; there is probably a syntax error here:
ThisWorkbook.Worksheets("Sheet1").OLEObjects("cmbS").ListFillRange = ar
when I do this I get:
"Type mismatch" error.
The result of this action should be that the component is populated with the array elements, from element(0) ... to the last element (n-1) of the array. Any pointers, thank you very much!
I also tried:
ThisWorkbook.Worksheets("Sheet1").cmbS.list = ar
and it says "permission denied"
Here are the combobox properties in case it helps:
After testing and trying, I found this works:
ThisWorkbook.Worksheets("Sheet1").cmbS.ListFillRange = ""
Dim i As Integer
For i = LBound(ar) To UBound(ar)
ThisWorkbook.Worksheets("Sheet1").cmbS.AddItem (ar(i))
Next
However, I am interested in populating with all values at once for faster effect, not just adding element by element.
I know its late but maybe it is going to help someone else. At least the following code works (much faster than element for element) for me.
dim arr() as variant
arr = Worksheets("Total").Range("C2:"&lrow).Value
Worksheets("Menu").ComboBox2.List = arr
The only way you can populate a combobox with the content of an array is by doing it element by element. I find it hard to believe that it would be a notably slow process no matter how large your array is.