how to populate userform list from pivot table? - listboxitem

I need to populate a pivot table on a User form and have been successful with using just one field but I need 4 fields to show up. here is what I have but keep getting errors:
Private Sub UserForm_Initialize()
Dim pvtTable As PivotTable
Dim pvtDeliv, pvtDoc, pvtName, pvtMaterial As PivotField
Dim lngIndex As Long
Dim arrData() As String
Set pvtTable = Worksheets("orders").PivotTables("orders")
Set pvtDoc = pvtTable.PivotFields("OriginDoc.")
Set pvtDeliv = pvtTable.PivotFields("Deliv.Date")
Set pvtMaterial = pvtTable.PivotFields("Material")
Set pvtName = pvtTable.PivotFields("Name")
ListBox1.ColumnCount = 4
For lngIndex = 1 To pvtDeliv.PivotItems.Count
UserForm1.ListBox1.AddItem pvtDeliv.PivotItems(lngIndex).Name.Value
ListBox1.List(lngIndex, 2) = pvtMaterial.PivotItems(lngIndex).Name.Value
ListBox1.List(lngIndex, 3) = pvtName.PivotItems(lngIndex).Name.Value
ListBox1.List(lngIndex, 4) = pvtDoc.PivotItems(lngIndex).Name.Value
Next
End Sub
That's the pivot table I'm trying to populate
Pivot table
thanks in advance.
Martyna

After some investigating I figured it out and here is the revised code:
Private Sub UserForm_Initialize()
Dim pvtTable As PivotTable
Dim pvtDeliv, pvtDoc, pvtName, pvtMaterial As PivotField
Dim lngIndex As Long
Dim arrData() As String
Set pvtTable = Worksheets("orders").PivotTables("orders")
Set pvtDoc = pvtTable.PivotFields("OriginDoc.")
Set pvtDeliv = pvtTable.PivotFields("Deliv.Date")
Set pvtMaterial = pvtTable.PivotFields("Material")
Set pvtName = pvtTable.PivotFields("Name")
ListBox1.ColumnCount = 4
For lngIndex = 1 To pvtDeliv.PivotItems.Count
UserForm1.ListBox1.AddItem
ListBox1.List(lngIndex - 1, 0) = pvtDeliv.PivotItems(lngIndex).Name
ListBox1.List(lngIndex - 1, 1) = pvtMaterial.PivotItems(lngIndex).Name
ListBox1.List(lngIndex - 1, 2) = pvtName.PivotItems(lngIndex).Name
ListBox1.List(lngIndex - 1, 3) = pvtDoc.PivotItems(lngIndex).Name
Next
End Sub

Related

Program closes before if statement (CATIA VBA)

I am trying to implement a minimum boundary box subroutine inside my macro. Subroutine ends before going into if statement. Can you help me find the solution?
Option Explicit
Sub bounding()
Dim partDocument1 As PartDocument
Set partDocument1 = CATIA.ActiveDocument
Dim part1 As Part
Set part1 = partDocument1.Part
Dim hybridShapeFactory1 As HybridShapeFactory
Set hybridShapeFactory1 = part1.HybridShapeFactory
Dim hybridBodies1 As HybridBodies
Set hybridBodies1 = part1.HybridBodies
Dim hybridBody1 As hybridbody
Set hybridBody1 = hybridBodies1.Item(cevap)
Dim hybridShapes1 As HybridShapes
Set hybridShapes1 = hybridBody1.HybridShapes
Dim axisSystems1 As AxisSystems
Set axisSystems1 = part1.AxisSystems
Dim axisSystem1 As AxisSystem
Set axisSystem1 = part1.FindObjectByName("axissys")
Dim direction As Long
If extindex Mod 2 = 1 Then
direction = 1
Else
direction = 0
End If
Dim reference1 As Reference
MsgBox CStr(extindex)
Select Case extindex
Case 1, 2
Set reference1 = axisSystem1.XAxisDirection
MsgBox CStr(extindex) + "1ve2"
Case 3, 4
Set reference1 = axisSystem1.YAxisDirection
MsgBox CStr(extindex) + "3ve4"
Case Else
Set reference1 = axisSystem1.YAxisDirection
MsgBox CStr(extindex) + "5ve6"
End Select
Debug.Print ("exit if check")
Dim hybridShapeDirection1 As HybridShapeDirection
Set hybridShapeDirection1 = hybridShapeFactory1.AddNewDirection(reference1)
Dim bodies1 As Bodies
Set bodies1 = part1.Bodies
Dim body1 As Body
Set body1 = bodies1.Item("PartBody")
Dim reference2 As Reference
Set reference2 = part1.CreateReferenceFromObject(body1)
Dim hybridShapeExtremum1 As HybridShapeExtremum
Set hybridShapeExtremum1 = hybridShapeFactory1.AddNewExtremum(reference2,
hybridShapeDirection1, 0)
part1.Update
hybridBody1.AppendHybridShape hybridShapeExtremum1
part1.InWorkObject = hybridShapeExtremum1
hybridShapeExtremum1.Name = "ext1" + CStr(extindex)
part1.Update
End Sub
All variables on the program are checked and they work. I don't understand what is happening an why it doesnt work. I even checked all variables. Program should go inside if statement but it doesnt
The AxisSystem properties XAxisDirection, YAxisDirection, and ZAxisDirection refer to the references from which the axis system was defined.
You can use these properties to edit the AxisSystem object itself but they are not "output" Reference objects which should be used to construct downstream geometry.
You can pull the vectors components using the GetXAxis, GetYAxis, and GetZAxis methods (which will always contain values) and then use HybridShapeFactory.AddDirectionFromCoord() method to create the direction for the extremum.
...
MsgBox CStr(extindex)
Dim vect(2)
Dim vAxis As Variant
Set vAxis = axisSystem1
Select Case extindex
Case 1, 2
vAxis.GetXAxis vect
Case 3, 4
vAxis.GetYAxis vect
Case Else
vAxis.GetYAxis vect
End Select
Dim hybridShapeDirection1 As HybridShapeDirection
Set hybridShapeDirection1 = hybridShapeFactory1.AddNewDirectionByCoord(vect(0), vect(1), vect(2))
...

VBA function cannot locate a bookmark

I am trying to call a REST web service in a VBA module to populate some bookmarks in a Word document. For some reason the code freezes at this line
Set cCap1 = ActiveDocument.Bookmarks("CCAP1").Range
cCap1.Text = keyResult.SelectSingleNode("//cCap").Text
saying that the bookmark "CCAP1" does not exist inside the document, when in fact is perfectly visible in the bookmarks list, as you see here
I checked the webservice and it returns a valid XML document which should not pose any problem.
Following you will find the complete VBA module code
Public Static Sub callRestService()
Dim idC As String
Dim custDate As String
Dim query As String
idC = mdlFormVal.getIdC
custDate = mdlFormVal.getCustDate
query = "http://path/to/webservice/service?key=" + idC
Dim keyResult As New MSXML2.DOMDocument60
Dim keyService As New MSXML2.XMLHTTP60
keyService.Open "GET", query, False
keyService.send
keyResult.LoadXML (keyService.responseText)
Dim cRas As Range
Dim cRas1 As Range
Dim cRas2 As Range
Dim cRas3 As Range
Dim cRas4 As Range
Dim cCap As Range
Dim cCap1 As Range
Dim cCap2 As Range
Dim cCf As Range
Dim cCf1 As Range
Dim cInd As Range
Dim cInd1 As Range
Dim cInd2 As Range
Dim cLoc As Range
Dim cLoc1 As Range
Dim cLoc2 As Range
Dim cPIva As Range
Dim cPIva1 As Range
Dim cPrvn As Range
Dim cPrvn1 As Range
Dim cPrvn2 As Range
Dim cusDate As Range
Set cRas = ActiveDocument.Bookmarks("CRAS").Range
cRas.Text = keyResult.SelectSingleNode("//cRas").Text
Set cRas1 = ActiveDocument.Bookmarks("CRAS1").Range
cRas1.Text = keyResult.SelectSingleNode("//cRas").Text
Set cRas2 = ActiveDocument.Bookmarks("CRAS2").Range
cRas2.Text = keyResult.SelectSingleNode("//cRas").Text
Set cRas3 = ActiveDocument.Bookmarks("CRAS3").Range
cRas3.Text = keyResult.SelectSingleNode("//cRas").Text
Set cRas4 = ActiveDocument.Bookmarks("CRAS4").Range
cRas4.Text = keyResult.SelectSingleNode("//cRas").Text
Set cCap = ActiveDocument.Bookmarks("CCAP").Range
cCap.Text = keyResult.SelectSingleNode("//cCap").Text
Set cCap1 = ActiveDocument.Bookmarks("CCAP1").Range
cCap1.Text = keyResult.SelectSingleNode("//cCap").Text
Set cCap2 = ActiveDocument.Bookmarks("CCAP2").Range
cCap2.Text = keyResult.SelectSingleNode("//cCap").Text
Set cCf = ActiveDocument.Bookmarks("CCF").Range
cCf.Text = keyResult.SelectSingleNode("//cCf").Text
Set cCf1 = ActiveDocument.Bookmarks("CCF1").Range
cCf1.Text = keyResult.SelectSingleNode("//cCf").Text
Set cInd = ActiveDocument.Bookmarks("CIND").Range
cInd.Text = keyResult.SelectSingleNode("//cInd").Text
Set cInd1 = ActiveDocument.Bookmarks("CIND1").Range
cInd1.Text = keyResult.SelectSingleNode("//cInd").Text
Set cInd2 = ActiveDocument.Bookmarks("CIND2").Range
cInd2.Text = keyResult.SelectSingleNode("//cInd").Text
Set cLoc = ActiveDocument.Bookmarks("CLOC").Range
cLoc.Text = keyResult.SelectSingleNode("//cLoc").Text
Set cLoc1 = ActiveDocument.Bookmarks("CLOC1").Range
cLoc1.Text = keyResult.SelectSingleNode("//cLoc").Text
Set cLoc2 = ActiveDocument.Bookmarks("CLOC2").Range
cLoc2.Text = keyResult.SelectSingleNode("//cLoc").Text
Set cPIva = ActiveDocument.Bookmarks("CPIVA").Range
cPIva.Text = keyResult.SelectSingleNode("//cPIva").Text
Set cPIva1 = ActiveDocument.Bookmarks("CPIVA1").Range
cPIva1.Text = keyResult.SelectSingleNode("//cPIva").Text
Set cPrvn = ActiveDocument.Bookmarks("CPRVN").Range
cPrvn.Text = keyResult.SelectSingleNode("//cPrvn").Text
Set cPrvn1 = ActiveDocument.Bookmarks("CPRVN1").Range
cPrvn1.Text = keyResult.SelectSingleNode("//cPrvn").Text
Set cPrvn2 = ActiveDocument.Bookmarks("CPRVN2").Range
cPrvn2.Text = keyResult.SelectSingleNode("cPrvn").Text
Set cusDate = ActiveDocument.Bookmarks("CUSTDATE").Range
cusDate.Text = custDate
End Sub
Has anyone ever encountered something like this?
Thank you for your time.
I managed to solve the issue, "simply" recreating all the document bookmarks.

Using Worksheet Functions In A Macro

I have an array of integers in VBA from which I would like to get the upper and lower quartiles.
I would like to use this method to get them: https://msdn.microsoft.com/en-us/library/office/ff836118.aspx
The documentation suggests you can use an array to do this, but when I try to run my code (below) I get an error saying Unable to get the Quartile property of the WorksheetFunction class
Please assist.
Dim totalsalesthatday() As String
Dim doINeedTo As Boolean
Dim totalsalesthatdayAverage As Integer
Dim randomnumberthingy As Integer
Dim quartile1 As Integer
Dim quartile3 As Integer
Dim iqr As Integer
Dim upper As Integer
Dim lower As Integer
quantity = 0
For Each queryaddress In worksheetname.Range("A2:A21")
query = queryaddress.Value
offsetnum = 0
If offsetnum = 0 Then
doINeedTo = True
End If
For Each daysoftheweek In Sheets
quantity = 0
If InStr(1, daysoftheweek.Name, worksheetnamename, vbTextCompare) > 0 And daysoftheweek.ListObjects.Count > 0 Then
Set itemaddress = daysoftheweek.Columns(5).Find(query, , xlValues, xlWhole)
If Not itemaddress Is Nothing Then
firstAddress = itemaddress.Address
Do
Set itemrow = itemaddress.EntireRow
quantity = quantity + itemrow.Columns(6).Value
Set itemaddress = daysoftheweek.Columns(5).FindNext(itemaddress)
Loop While Not itemaddress Is Nothing And itemaddress.Address <> firstAddress
End If
offsetnum = offsetnum + 1
ReDim Preserve totalsalesthatday(offsetnum)
totalsalesthatday(offsetnum) = daysoftheweek.ListObjects.Item(1).ListRows.Count
queryaddress.Offset(0, offsetnum).Value = quantity
worksheetname.Range("A1").Offset(0, offsetnum).Value = daysoftheweek.Name
End If
Next
If doINeedTo Then
quartile1 = WorksheetFunction.Quartile(totalsalesthatday, 1)
quartile3 = WorksheetFunction.Quartile_Inc(totalsalesthatday, 3)
iqr = quartile3 - quartile1
upper = quartile3 + (iqr * 1.5)
lower = quartile1 - (iqr * 1.5)
The error in question is at this line: quartile1 = WorksheetFunction.Quartile(totalsalesthatday, 1)
The .Quartile function parameters are an array and a double. Try changing your data types.

A practical example of evenly distributing n lists into a single list

I had previously asked about how to evenly distribute the items in n lists into a single list and was referred to this question: Good algorithm for combining items from N lists into one with balanced distribution?.
I made a practical example of my solution for this in VBA for Excel, since my application for this was resorting my Spotify lists which can be easily pasted into Excel for manipulation. Assumptions are that you have a headerless worksheet (wsSource) of songs with columns A, B, C representing Artist, Song, SpotifyURI respectively, a "Totals" worksheet (wsTotals) containing the sum of songs for each Artist from wsSource sorted in descending order, and a "Destination" worksheet where the new list will be created. Could I get some suggestions to improve this? I was going to get rid of the totals worksheet and have this portion done in code, but I have to go and I wanted to go ahead and put this out there. Thanks!
Sub WeaveSort()
Dim wb As Workbook
Dim wsDest As Worksheet
Dim wsSource As Worksheet
Dim wsTotals As Worksheet
Dim i As Integer
Dim iLast As Integer
Dim iDest As Integer
Dim iSource As Integer
Dim iOldRow As Integer
Dim iNewRow As Integer
Dim dDiff As Double
Dim dDiffSum As Double
Set wb = ThisWorkbook
Set wsTotals = wb.Worksheets("Totals")
Set wsSource = wb.Worksheets("Source")
Set wsDest = wb.Worksheets("Dest")
iLast = wsTotals.Range("A1").End(xlDown).Row - 1
For i = 2 To iLast
iSource = wsTotals.Range("B" & i).Value
iDest = wsDest.Range("A99999").End(xlUp).Row
If i = 2 Then
wsDest.Range("A1:C" & iSource).Value2 = wsSource.Range("A1:C" & iSource).Value2
wsSource.Range("A1:C" & iSource).Delete (xlShiftUp)
GoTo NextI
End If
dDiff = iDest / iSource
dDiffSum = 0
iNewRow = 0
For iOldRow = 1 To iSource
dDiff = iDest / iSource
dDiffSum = dDiffSum + dDiff
iNewRow = Round(dDiffSum, 0)
wsSource.Rows(iOldRow).Copy
wsDest.Rows(iNewRow).Insert xlShiftDown
iDest = iDest + 1
Next iOldRow
wsSource.Range("A1:C" & iSource).Delete (xlShiftUp)
NextI:
Next i
End Sub
Great question! I would take an object oritentated approach. Also I didn;t think it was clear what the logic was so here is my answer. Two classes and one normal module. Save these separately with the filenames ListManager.cls, List.cls, tstListManager.bas
So the ListManager.cls is this
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "ListManager"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit
Private mdic As Object
Public Sub Initialise(ByVal vLists As Variant)
Set mdic = VBA.CreateObject("Scripting.Dictionary")
Dim vListLoop As Variant
For Each vListLoop In vLists
Dim oList As List
Set oList = New List
oList.Initialise vListLoop, ""
mdic.Add mdic.Count, oList
Next
End Sub
Public Function WeaveSort() As Variant
Dim dicReturn As Object
Set dicReturn = VBA.CreateObject("Scripting.Dictionary")
Dim oNextList As List
Set oNextList = Me.WhichListHasLeastProgress
While oNextList.PercentageDone <= 1
Dim vListItem As Variant
vListItem = oNextList.GetListItem
dicReturn.Add dicReturn.Count, vListItem
oNextList.MoveNext
Set oNextList = Me.WhichListHasLeastProgress
Wend
Dim vItems As Variant
vItems = dicReturn.Items
'I don't like this bit
ReDim vRet(1 To dicReturn.Count, 1 To 1)
Dim lLoop As Long
For lLoop = 0 To dicReturn.Count - 1
vRet(lLoop + 1, 1) = vItems(lLoop)
Next lLoop
WeaveSort = vRet
End Function
Public Function WhichListHasLeastProgress() As List
Dim vKeyLoop As Variant
Dim oListLoop As List
Dim oLeastProgress As List
For Each vKeyLoop In mdic.keys
Set oListLoop = mdic.Item(vKeyLoop)
If oLeastProgress Is Nothing Then
'nothing to compare yet
Set oLeastProgress = oListLoop
Else
If oListLoop.PercentageDone < oLeastProgress.PercentageDone Then
'definitely take this new candidate
Set oLeastProgress = oListLoop
ElseIf oListLoop.PercentageDone = oLeastProgress.PercentageDone And oListLoop.Size > oListLoop.Size Then
'close thing, both showing equal progress but we should give it to the one with the bigger "queue"
Set oLeastProgress = oListLoop
Else
'no swap
End If
End If
Next
'return the answer
Set WhichListHasLeastProgress = oLeastProgress
End Function
and the List.cls file is
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "List"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit
Private mvList As Variant
Private mlCount As Long
Private mlCursor As Long
Private mvName As Variant
Public Function Initialise(ByRef vList As Variant, ByVal vName As Variant)
Debug.Assert TypeName(vList(1, 1)) <> "" ' this will break unless you specify a 2d array
Debug.Assert LBound(vList, 1) = 1 ' this ensure you got it from a sheet
mvList = vList
mlCount = UBound(mvList)
mlCursor = 1
mvName = vName
End Function
Public Function GetListItem()
GetListItem = mvList(mlCursor, 1)
End Function
Public Function Name() As Variant
Name = mvName
End Function
Public Function MoveNext() As Boolean
mlCursor = mlCursor + 1
MoveNext = (mlCursor < mlCount)
End Function
Public Function Size() As Long
Size = mlCount
End Function
Public Function PercentageDone() As Double
PercentageDone = mlCursor / mlCount
End Function
The last file is this tstListManager.bas
Attribute VB_Name = "tstListManager"
Option Explicit
Sub test()
Dim oListMan As ListManager
Set oListMan = New ListManager
Dim vLists As Variant
vLists = VBA.Array(ThisWorkbook.Sheets("Source").Range("A1:A3").Value2, _
ThisWorkbook.Sheets("Source").Range("B1:B2").Value2, _
ThisWorkbook.Sheets("Source").Range("C1:C5").Value2)
oListMan.Initialise vLists
Dim vSorted As Variant
vSorted = oListMan.WeaveSort
Dim lTotal As Long
ThisWorkbook.Sheets("Dest").Range("A1").Resize(UBound(vSorted, 1)).Value2 = vSorted
End Sub
Finally, the test data was in A1:A3 B1:B2 C1:C5
You should note I have abstracted away any Excel reading/writing logic and the pure weavesort logic is not cluttered.
Feel free to reject outright. Object orientation can be quite controversial and we think differently. :)

Excel VBA array data source for Chartspace in Userform

I try to generate a barchart within an Excel Userform - Chartspace Is there any possibility to use VBA generated array data as source for the bar chart. I can only find description for Spreadsheet as source.
Private Sub UserForm_Activate()
Dim z As Long, s As Integer
Dim cc
Dim ch1
Dim pt
For z = 1 To 9
For s = 1 To 2
Spreadsheet1.ActiveSheet.Cells(z, s) = Sheets("Tabelle1").Cells(z, s)
Next
Next
Set cc = ChartSpace1.Constants
Set ChartSpace1.DataSource = Spreadsheet1 '<-- does it need linked to a spreadsheet?
Set ch1 = ChartSpace1.Charts.Add
ch1.Type = cc.chChartTypeLineMarkers
ch1.SetData 1, 0, "A2:A9"
ch1.SeriesCollection(0).SetData 2, 0, "B2:B9"
End Sub
Is the a other way to show a bar chart in a userform where I can use the array source?
Thanks a lot.
Perhaps this suggests how to do it:
http://msdn.microsoft.com/en-us/library/office/aa193650(v=office.11).aspx
This example (slightly modified so that I could test from the link above) creates a chart using literal data arrays.
Output Example
Code Example
Sub BindChartToArrays()
Dim asSeriesNames(1)
Dim asCategories(7)
Dim aiValues(7)
Dim chConstants
Dim chtNewChart
Dim myChtSpace As ChartSpace
asSeriesNames(0) = "Satisfaction Data"
asCategories(0) = "Very Good"
asCategories(1) = "Good"
asCategories(2) = "N/A"
asCategories(3) = "Average"
asCategories(4) = "No Response"
asCategories(5) = "Poor"
asCategories(6) = "Very Poor"
aiValues(0) = 10
aiValues(1) = 22
aiValues(2) = 6
aiValues(3) = 31
aiValues(4) = 5
aiValues(5) = 14
aiValues(6) = 12
Set myChtSpace = UserForm1.ChartSpace1
Set chConstants = myChtSpace.Constants
' Add a new chart to Chartspace1.
Set chtNewChart = myChtSpace.Charts.Add
' Specify that the chart is a column chart.
chtNewChart.Type = chConstants.chChartTypeColumnClustered
' Bind the chart to the arrays.
chtNewChart.SetData chConstants.chDimSeriesNames, chConstants.chDataLiteral, asSeriesNames
chtNewChart.SetData chConstants.chDimCategories, chConstants.chDataLiteral, asCategories
chtNewChart.SeriesCollection(0).SetData chConstants.chDimValues, chConstants.chDataLiteral, aiValues
UserForm1.Show
End Sub