I am creating a PivotTable from an Excel Sheet using VBA PivotTableWizard method.
I do define two row fields and two data fields with sum function. By default the name of the data fields appear in the Pivot Table as row description right from the row field names.
I wish to display the name of the data fields as column headers. In the Wizard the user would drag the "Sum sign - Values" field into the Column Labels box. How can this be done by code?
This is what I do have so far:
' Create the PivotTable object based on the data on the selected sheet
Set tm_volumes_pivot_table = ActiveSheet.PivotTableWizard
'Page fields
Set tm_volumes_pivot_field = tm_volumes_pivot_table.PivotFields("Article Type")
tm_volumes_pivot_field.Orientation = xlPageField
'Row fields
Set tm_volumes_pivot_field = tm_volumes_pivot_table.PivotFields("Main Area")
tm_volumes_pivot_field.Orientation = xlRowField
Set tm_volumes_pivot_field = tm_volumes_pivot_table.PivotFields("Subarea")
tm_volumes_pivot_field.Orientation = xlRowField
'Column fields
'Must be Names of Data Fields - how?
'Data fields
Set tm_volumes_pivot_field = tm_volumes_pivot_table.PivotFields("Initial Volume")
tm_volumes_pivot_field.Orientation = xlDataField
tm_volumes_pivot_field.Function = xlSum
tm_volumes_pivot_field.NumberFormat = "#"
Set tm_volumes_pivot_field = tm_volumes_pivot_table.PivotFields("Final Volume")
tm_volumes_pivot_field.Orientation = xlDataField
tm_volumes_pivot_field.Function = xlSum
tm_volumes_pivot_field.NumberFormat = "#"
Transfer OP's answer from question:
When a pivot table is going to have more than one data field, there is a virtual field named Values in the drop zones of the PivotTable Field List. In VBA, this equivalent virtual field is named "Data". - This will be used to arrange the Data in columns.
'Define Pivot Fields (Rows / Columns - Attention to "Data" / Page)
tm_volumes_pivot_table.AddFields Array("Main Area", "Subarea"), "Data", "Article Type"
Related
I want to open excel and have a textbox pop up. whatever string the user inputs in the text box will be the variable that is used in Power Query data loaded into the worksheet.
I currently have this M code:
let
Source = Sql.Databases("BMCCL006.DS.BUILDWITHBMC.COM\DW", [HierarchicalNavigation=true]),
trendsql = Source{[Name="trendsql"]}[Data],
dbo = trendsql{[Schema="dbo"]}[Data],
poeh1 = dbo{[Name="poeh"]}[Data],
#"Removed Other Columns" = Table.SelectColumns(poeh1,{"pono", "posuf", "stagecd", "shiptonm", "enterdt", "whse", "vendno", "takenby"}),
#"Filtered Rows" = Table.SelectRows(#"Removed Other Columns", each [stagecd] < 3),
#"Filtered Rows1" = Table.SelectRows(#"Filtered Rows", each [takenby] = "mytextboxstring"),
#"Changed Type" = Table.TransformColumnTypes(#"Filtered Rows1",{{"enterdt", type date}}),
#"Filtered Rows2" = Table.SelectRows(#"Changed Type", each true),
#"Sorted Rows" = Table.Sort(#"Filtered Rows2",{{"enterdt", Order.Descending}})
in
#"Sorted Rows"
I want to use the textbox ("mytextboxstrig") to be the value of to filter the rows by in [takenby].
can this be done through VBA so that this query runs and loads to worksheets("Sheet1")?
Thank you.
1 Create a range name, here aaa
2 Use VBA to populate it
Private Sub Workbook_Open()
Range("aaa").Value = _
InputBox(Prompt:="Type the value you want")
End Sub
3 Refer to the named range in powerquery
NameValue= Excel.CurrentWorkbook(){[Name="aaa"]}[Content]{0}[Column1],
#"Filtered Rows" = Table.SelectRows(#"YourPriorStepName", each ([takenby] = NameValue))
It is above my possibilities.
I know how to create Vba code with Vlookup or Hlookup for single comparision. However whatIi am trying is beyond my knowledge.
I need to compare 2 tables. 1st is requirements where 2nd is DB extract.
Both tables contains same "Action" column and other columns with Employer role as a header. Values from Action column for both tables are the same however in different order ( Those values need to act as primary key).
Columns with Employer role as a header - same header value for both tables - however columns in different order.
Amount of columns with Employer role as a header is not constants and it gets change every time I get this files. Those columns in extract are in different order than in requirements.
Amount of values from "Action" columns ( primary key) also not constants and change every time I receive files. So I cannot set specific range.
Example of Requirements table
Example of Extract table
Example of what is expected
New target worksheet need to be created where Comparison table will be created.
VBA to create Comparison table in newly created worksheet.
This table should have "Action" column + all columns with Employers role as header form requirements + all columns with Employers role as header form extract set in same order like columns in requirements + comparison table which compare values between Employers roles from Requirements and Extract and show values YES or NO
Try the next code, please. It will return in a newly created sheet (after the last existing). The new file is named "New Sheet". If it exists, it is cleared and reused:
Sub testMatchTables()
Dim sh As Worksheet, sh1 As Worksheet, shNew As Worksheet
Dim tbl1 As ListObject, tbl2 As ListObject, rightH As Long
Dim arrR, arrE, arrH1, arrH2, arrFin, i As Long, j As Long, k As Long
Dim first As Long, sec As Long, refFirst As Long, refSec As Long
Set sh = Set sh = Worksheets("Requirements")'use here the sheet keeping the first table
Set sh1 = Worksheets("Extract Table") 'use here your appropriate sheet
Set tbl1 = sh.ListObjects(1) 'use here your first table name (instead of 1)
Set tbl2 = sh1.ListObjects(1) 'use here your second table name (instead of 1)
arrR = tbl1.Range.value 'put the table range in an array
arrE = tbl2.Range.value 'put the table range in an array
'working with arrays will condiderably increase the processing speed
ReDim arrFin(1 To UBound(arrR), 1 To UBound(arrR, 2) * 3 + 2) 'redim the array to keep the processing result
'UBound is a property telling the number of array elements
arrH1 = Application.Index(arrR, 1, 0) 'make a slice in the array (1D array), the first row, which keeps the headers
arrH2 = Application.Index(arrE, 1, 0) 'make a slice in the array (1D array), the first row, which keeps the headers
'build the column headers:
For i = 1 To UBound(arrFin, 2)
If i <= UBound(arrH1) Then 'firstly the headers of the first table are filled in the final array
arrFin(1, i) = arrH1(i)
ElseIf refSec = 0 Then 'refSec is the column where a blanck column will exist
first = first + 1 'the code incrementes this variable to allow making empty only for the following row
If first = 1 Then
arrFin(1, i) = Empty: refFirst = i 'make the empty column between the two tables data and create a reference
'to be decreated from the already incremented i variable
Else
arrFin(1, i) = arrH1(i - refFirst) 'place each header column values
If i - refFirst = UBound(arrH1) Then refSec = i + 1 'when the code reaches the end of the first array
'it creates a reference for referencing the second time
End If
Else
sec = sec + 1 'the same philosophy as above, to create the second empty column
If sec = 1 Then
arrFin(1, i) = Empty 'create the empty column (for each processed row)
Else
arrFin(1, i) = arrH1(i - refSec) 'fill the header columns
End If
End If
Next
Dim C As Long, r As Long, eT As Long, T As Long
eT = UBound(arrR) 'mark the ending of the first array (where to be the first empty column)
T = UBound(arrR, 2) * 2 + 2 'mark the begining of the third final array part
'after the second empty column
For i = 2 To UBound(arrR) 'iterating between the first array rows
For j = 2 To UBound(arrE) 'iterating the second array rows
If arrR(i, 1) = arrE(j, 1) Then 'if the both arrays first column matches
arrFin(i, 1) = arrR(i, 1): arrFin(i, T + 1) = arrR(i, 1) 'put the Action values in the first area columns
arrFin(i, eT) = arrR(i, 1) 'put the Action values in the last area column
For C = 2 To UBound(arrR, 2) 'iterate between the array columns
rightH = Application.match(arrR(1, C), arrH2, 0) 'find the match of the first array header in the second one
arrFin(i, C) = arrR(i, C): arrFin(i, C + eT - 1) = arrE(j, rightH) 'place the matching header in the final array
If arrR(i, C) = arrE(j, rightH) Then
arrFin(i, T + C) = "TRUE" 'place 'TRUE' in case of matching
Else
arrFin(i, T + C) = "FALSE" 'place 'FALSE' in case of NOT matching
End If
Next C
End If
Next j
Next i
On Error Resume Next 'necessary to return an error if worksheet "New Sheet" does not exist
Set shNew = Worksheets("New Sheet")
If err.Number = 9 Then 'if it raises error number 9, this means that the sheet does not exist
err.Clear: On Error GoTo 0 'clear the error and make the code to return other errors, if any
Set shNew = Worksheets.Add(After:=Worksheets(Worksheets.count)) 'set shNew as new inserted sheet
shNew.name = "New Sheet" 'name the newly inserted sheet
Else
shNew.cells.Clear: On Error GoTo 0 ' in case of sheet exists, it is clear and the code is made to return errors
End If
'set the range where the final array to drop its values:
With shNew.Range("A1").Resize(UBound(arrFin), UBound(arrFin, 2))
.value = arrFin 'drop the array content
.EntireColumn.AutoFit 'AutoFit the involved columns
End With
End Sub
Please, test it and send some feedback.
Edited:
I commented the code as detailed I could. If still something unclear, please do not hesitate to ask for clarifications.
I am getting data from Access, copying into Excel sheet and creating a chart using Excel VBA. The data looks like this:
And the chart looks like this:
I want to show all transactions in sheet but in chart I want to show sum of amount of dates. For example on 19/08/2015 total amount 2695, 20/08/2015 total amount 287.
How can I create a chart in VBA Excel to show the sum of each day?
I agree with #ChipsLetten
1.- From SQL you could use something like this:
---- This is the sum for each day
SELECT
t.DOT, SUM(t.Amount)
---- You can add an extra Column with the SUM by Dates
/*
t.Dot, t.Category, t.Item, t.Amount
, SUM(t.Amount) OVER(PARTITION BY t.Dot ORDER BY t.Dot) [SumTrans]
*/
FROM Transactions t
GROUP BY t.DOT
-- If you add the Column you must change "GROUP BY"
-- GROUP BY t.Dot, t.Category, t.Item, t.Amount
Adding the column you could use the DOT and SumTrans series to create the Chart
2.- With pivot table is even better, you can clone your Recordset to create a pivot table that allows you to SUM Amount by DOT
*Wkb is a Workbooks object, Wks is a Worksheet object*
Dim oRstChrt As ADODB.Recordset, oStrm As ADODB.Stream
Dim oChrt As Chart
'' Copy Recordset for the pivot table cache
Set oRstChrt = New ADODB.Recordset
Set oStrm = New ADODB.Stream
'' Create an alternative Recordset for the new pivot table
oRst.Save oStrm
oRstChrt.Open oStrm
'' Set Recordset to cache for a pivot table
Set objPivotCache = _
Wkb.PivotCaches.Create(SourceType:=xlExternal, Version:=xlPivotTableVersion14)
'' Recordset with Data
Set objPivotCache.Recordset = oRstChrt
'' Assign Range for the pivot table and Name it.
With objPivotCache
.CreatePivotTable TableDestination:=Wks.Range([Cell]), TableName:=[PivotTable_Name]
End With
Afterwards put the fields you need,
in this case DOT and Amount
With Wks.PivotTables([PivotTable_Name])
With .PivotFields("DOT")
.Orientation = xlRowField
.Position = 1
End With
'' You can create a second level, but
'' if the field is not collapse, your chart will change,
'' so keep the field collapse
'' To Collapse the field put this
'' Wks.PivotTables([PivotTable_Name]). _
'' PivotFields([PivotTableField]).ShowDetail = False
'With .PivotFields("Item")
'.Orientation = xlRowField
'.Position = 2
'End With
'' This allows you to SUM the Amount field
.AddDataField .PivotFields("Amount"), "Total Amount", xlSum
End
'' After the Pivot Table was created you can create your chart
'' Set the object
Set oChrt = Charts.Add
'' Give a name and format
With oChrt
.Name = "[Chart_Name]"
.ChartType = xlColumnClustered '' you could change to 3D
'' Source Range in this case from the pivot table
.SetSourceData Source:=Wks.PivotTables([PivotTable_Name]).TableRange2, _
PlotBy:=xlRows
'' Format chart
.HasTitle = True
.ChartTitle.Text = "Total Transactions"
.Axes(xlCategory, xlPrimary).HasTitle = True
.Axes(xlCategory, xlPrimary).AxisTitle.Characters.Text = "Dates"
' .Axes(xlValue, xlPrimary).HasTitle = True
' .Axes(xlValue, xlPrimary).AxisTitle.Characters.Text = "Transactions"
End With
You have two choices:
Run another SQL query using SUM and GROUP BY to give you the totals. This is the data for your chart.
Look at using Pivot Charts in Excel. This will calc the totals for you and also draw the chart.
I create a Pivot Table with a VBScript in QLikView:
sub cleanUp()
set sheet = ActiveDocument.Sheets("Summary")
set summaryTable = sheet.CreatePivotTable
summaryTable.addDimension "Product Group Desc"
summaryTable.addDimension "Product Type Desc"
summaryTable.addDimension "Product Sub Group Desc"
summaryTable.addDimension "Country"
summaryTable.addDimension "ZoneMgrName"
summaryTable.addExpression "Sum({<[Fiscal Year]={$(vCurrentYear)}>}
[Sales Amount])"
set props = summaryTable.getProperties
set expr = props.Expressions.Item(0).Item(0).Data.ExpressionVisual
expr.Label.v = "Expenses $(vCurrentYear)"
expr.NumAdjust = 1 'center
expr.LabelAdjust = 1 'center
summaryTable.SetProperties props
end sub
In addition I would like to create new fields used as dimensions. These fields are not in my QLikView document so far. The value for these fields is linked to the value of other fields. Say I have a field Country in my Pivot Table. I would like to add a new Field "Area" which contains the name of the area which the country belongs to. So that the values for the field would be the return value of a function which returns the area for a given country.
It depends on how your "lookup" data is accessed (whether it resides in your QlikView document, or is external), but you are free to add calculated dimensions to your pivot via the addDimension method. For example:
summaryTable.addDimension "=if(Country='France', 'EU', 'non-EU')"
You can use any normal expression that can return meaningful values for your dimension.
If you wish to name the dimension, you can use addDimension's return value as follows:
dimensionNum = summaryTable.addDimension("=if(Country='France', 'EU', 'non-EU')")
set tableProperties = summaryTable.getProperties
set calcDim = tableProperties.Dimensions.Item(dimensionNum-1)
calcDim.Title.v = "Area"
summaryTable.SetProperties tableProperties
Is it possible to set a selected Data Grid View column name to a variable.
Example of my code.
Dim cmevoids As DataTable = ds.Tables(0)
Dim test As String
test = "event_code"
Dim Query = From payments In cmevoids.AsEnumerable() _
Where payments.Field(Of String)("event_code") = "MB120117"
Where payments.Field(Of String)("event_transaction_status") = "PAID"
Order By payments.Field(Of String)("event_code") _
Select New With {.event_code = payments.Field(Of String)(test), _
.event_transaction_status = payments.Field(Of String)("event_transaction_status"), _
.event_transaction_detail_amount = payments.Field(Of String)("event_transaction_detail_amount")}
dgvQuery.DataSource = Query.ToList()
I want to take w/e column the user selects from a combo box from the first data grid view and display it in a 2nd data grid view for query's.
I can get it to search and display the table selected by the variable given as shown by the test variable. But i can't get it to change the column name in the query data grid view to the name of the variable. I can only get it to name it w/e i have hard coded in, in this case event_code, event_transaction_status and event_transaction_detail_amount.
Any way to do this without hard code but variable?
What about populating the gridview like you have been but then change it after it is bound?
Dim Result as string = "w/e column the user selects from a combo box"
Dim i as integer = 0 'your colum index
GridView1.Columns(i).HeaderText = Result