Good day to all.
For the past 8hrs, I am looking for a pivot alternative in Access 2007 since the reference dll is not available in our Citrix account (OWC10.dll). So I did all the effort I could do to research workaround on this but I have nothing so far, so I think its time for a little help.
What I have here is a sample of the raw data..
This is the end result I am looking for, a pivot table, in which of course, can be viewed in a form (best solution) or to an extracted excel file.
So basically, I need to display:
how much time they worked each day
how many they worked each day.
I tried the TRANSFORM Statement/Crosstab and I get the error that there is too much rows to make it a column since I do have 20,000+ rows - 30days/month * people who worked. - DISTINCT them, but I dont know how?
I don't have the .dll file in our system, so normal pivoting is out of question. Does anyone know any alternatives that can give me these display results?
What you'll need to do is compile a query of the data you require, and push this into excel, then programmatically build a pivot table in excel, from access.
I use ADO for pretty much everything - so the syntax I've got here reflects this; If you DAO, you'll need to translate it.
sql = _
"SELECT Name, ProcessDate, HandlingTime " & _
"FROM tbl ... WHERE ..."
GenerateSimplePivot(excel_path&file_name_to_create, sql, 2)
Private Sub GenerateSimplePivot(xname As String, auditData As String, _ pivotColumns As Long)
Dim ii As Long
Dim XL As Object
Dim WB As Object
Dim WS1 As Object
Dim WS2 As Object
Dim rst As ADODB.Recordset
'create/assign xl objects
Set XL = CreateObject("Excel.Application")
XL.Visible = False
XL.DisplayAlerts = False
Set WB = XL.Workbooks.Add
Set WS1 = WB.Worksheets(1)
Set rst = New ADODB.Recordset
rst.Open auditData, CurrentProject.Connection, adOpenKeyset, adLockReadOnly
For ii = 0 To rst.Fields.Count - 1
WS1.Cells(1, ii + 1) = rst.Fields(ii).Name
Next
WS1.Range("A2").CopyFromRecordset rst
WS1.Columns.Autofit
WS1.Name = "AuditData"
For ii = 0 To rst.Fields.Count - 1
'add column formatting logic here, if required
Next
rst.Close
If WB.Worksheets.Count < 2 Then
Set WS2 = WB.Worksheets.Add(, WB.Worksheets(WB.Worksheets.Count))
Else
Set WS2 = WB.Worksheets(2)
End If
WS2.Name = "PivotTable"
DoCmd.SetWarnings False
Dim PTcache As Object
Dim pt As Object
WS1.Activate
Set PTcache = WB.PivotCaches.Add(SourceType:=xlDatabase, SourceData:=WS1.Range("A1").CurrentRegion.Address)
Set pt = PTcache.CreatePivotTable(TableDestination:=WS2.Range("a6"), TableName:="PivotTable ")
WS2.Activate
With pt
For ii = (pivotColumns - 3) To 2 Step -1
.PivotFields(ii).Orientation = xlPageField
Next
On Error Resume Next
.PivotFields(1).Orientation = xlPageField
Err.Clear
ON Error GoTo [error handler label]
.PivotFields(pivotColumns - 2).Orientation = xlRowField
.PivotFields(pivotColumns - 1).Orientation = xlColumnField
.PivotFields(pivotColumns).Orientation = xlDataField
End With
WB.SaveAs FileName:=xname
WB.Close
Set WS1 = Nothing
Set WS2 = Nothing
Set PTcache = Nothing
Set pt = Nothing
Set WB = Nothing
XL.Quit
DoCmd.SetWarnings True
Set rst = Nothing
Set WS1 = Nothing
Set WS2 = Nothing
Set PTcache = Nothing
Set pt = Nothing
Set WB = Nothing
Set XL = Nothing
End Sub
Is this what you were after?
For others who are having the same trouble as I am. I made a solution using CrossTab.
Using the Query Wizard is very easy and understandable. Below is the edited SQL query to suit my needs:
TRANSFORM format(Sum(MyCopy.[Duration]), "hh:mm:ss") AS SumOfDuration
SELECT MyCopy.[UserID].[FullName], MyCopy.[TL], Sum(MyCopy.[Duration]) AS [Total Of Duration]
FROM MyCopy
Group BY MyCopy.[UserID], MyCopy.[FullName], MyCopy.[TL]
PIVOT MyCopy.[Process Date];
Note: For report purposes, its very easy to just extract this query. I did use format so that it won't look ugly with the decimals. Apparently, MS Access does not give the answers real numbers, but same percentage. It solves differently when sum of total duration passes 24hrs. So I left it on decimal format for correct numbers to appear.
Related
Is there any way to Style a table with VBScript? All the solutions I'm finding online are for VBA.
for example, I tried the solution here Excel Macro - Select all cells with data and format as table with the following code
Set objExcel = CreateObject("Excel.Application")
Dim tbl
Set tbl = objWorkbook.ListObjects.Add(xlSrcRange, objWorkbook.Sheets("101").Range("$A$1:$C$26"), , xlYes)
tbl.TableStyle = "TableStyleLight1"
but I get this error
Microsoft VBScript runtime error: Object doesn't support this property or method: 'objWorkbook.ListObjects'
(If you have a solution for this in exceljs that would be even better)
I found something you may be able to use. It is from Using Styles to Dress Up Your Worksheets in Excel 2007. What I did was converted it from VBA to VBScript, which really wasn't that hard.
Sub ListStyles()
Dim objStyle
Dim objCellRange
Dim lngCount
Dim objSheet
Set objSheet = ThisWorkbook.Worksheets("Config - Styles")
With objSheet
lngCount = objSheet.UsedRange.Rows.Count + 1
For Each objStyle In ThisWorkbook.Styles
On Error Resume Next
Set objCellRange = Nothing
Set objCellRange = Intersect(objSheet.UsedRange, objSheet.Range("A:A")).Find(objStyle.Name, _
objSheet.Range("A1"), xlValues, xlWhole, , , False)
If objCellRange Is Nothing Then
lngCount = lngCount + 1
.Cells(lngCount, 1).Style = objStyle.Name
.Cells(lngCount, 1).Value = objStyle.NameLocal
.Cells(lngCount, 2).Style = objStyle.Name
End If
Next
End With
End Sub
To set this up, double click on the Sheet1 tab and rename it "Config - Styles". Add the code above, then run the script. What you end up with is this:
I have an Access 2010 application where I run a SQL query and output the results to Excel. I'm using the Excel subtotal command to create subtotals. That works fine, but on the total rows only the text ("XXX Count") is bold and the values are not bold. Our client would like the entire row bold. I've tried a couple ways without success. How do I do the entire row in the subtotals?
So here is what I currently have:
This is correct except I need all of row 5, 8, 16, and 17 bold like this:
Here is my code to create the Excel file from Access (this all works except for the bold issues):
Public Sub ExportToExcel(query)
Dim appXL As Object
Dim wbk As Object
Dim wksNew As Object
Set appXL = CreateObject("Excel.Application")
Set wbk = appXL.Workbooks.Add
Set wksNew = wbk.Worksheets("Sheet1")
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Set appXL = CreateObject("Excel.Application")
appXL.Visible = True
Set wbk = appXL.Workbooks.Add
Set wksNew = wbk.Worksheets(1)
Set cn = CurrentProject.AccessConnection
Set rs = New ADODB.Recordset
With rs
Set .ActiveConnection = cn
.Source = query
.Open
End With
With rs
'Put recordset into new wks
wksNew.Cells(2, 1).CopyFromRecordset rs
'And add headers
Dim i As Long
For i = 0 To .Fields.Count - 1
wksNew.Cells(1, i + 1).Value = .Fields(i).Name
wksNew.Cells(1, i + 1).Font.Bold = True
wksNew.Cells(1, i + 1).HorizontalAlignment = xlCenter
Next i
'Now, while the recordset is available...
'The recordset has .fields.count fields
'Subtotals are wanted from field 7 to the end
If .Fields.Count > 13 Then
ReDim ary(14 To .Fields.Count - 1)
For i = LBound(ary) To UBound(ary)
ary(i) = i
Next i
wksNew.Cells(1, 1).CurrentRegion.SubTotal GroupBy:=1, _
TotalList:=ary, Replace:=True, PageBreaks:=False, SummaryBelowData:=True
End If
.Close
End With
End Sub
I tried this code based on this website:
Dim rCell As Range
wksNew.Columns("A:A").Select
Dim rCell As Range
For Each rCell In Selection
If Right(rCell.Value, 5) = "Count" Then
Rows(rCell.Row).Interior.ColorIndex = 36
End If
Next
but it returned a "Method or data member not found" error on the item rCell.Value.
I also tried it like this:
Dim rCell As Range
wksNew.Columns("A:A").Select
For Each rCell In Selection
If Right(rCell, 5) = "Count" Then
Selection.Font.Bold = True
End If
Next
But I got the error "ActiveX component can't create object" on the For Each line.
How do I bold the entire row for the subtotals?
You're getting an error because Access doesn't know what Selection is unless you tell it that it's connected to your Excel instance.
For Each rCell In Selection
However, don't need to select anything, or check the whole column:
Dim rCell As Range
For Each rCell In wksNew.UsedRange.Columns(1).Cells
If Right(rCell, 5) = "Count" Then
rCell.Font.Bold = True
End If
Next
Have you tried a Pivot Table?? It is easier to manage format or layout and you don't have to change too much your code because you just put your RecordSet in a PivotTableCache like the second example in this.
Rather than looping, I'd suggest collapsing the outline and formatting the visible cells:
with wksNew.Cells(1, 1).CurrentRegion
.Outlinelevel = 2
.specialcells(12).Font.Bold = True
.Outlinelevel = 3
End With
Thanks for all the suggestions. No one posted a solution that worked entirely, so here's what I ended up using:
Dim c As Object
For Each c In wksNew.Range("A1:A500")
If c.Value Like "*Total" Then
c.Offset(0, 13).Font.Bold = True
c.Offset(0, 14).Font.Bold = True
c.Offset(0, 15).Font.Bold = True
End If
Next
The only thing that concerns me is that I'm assuming this only has 500 rows. I couldn't find a way to find the number of rows and have it search only those. If I included the whole column, it took a couple minutes to complete the loop which I didn't think the client would like. Any suggestions on how to find the last row?
I would
Display level 2 of the outline, all the subtotals
Select the whole area
Use GoTo Special to select only visible cells
Apply the formatting
Change the header row formatting if it should be different
Display all the levels again (level 3)
This code demonstrates:
Sub Macro4()
Application.ScreenUpdating = False
ActiveSheet.Outline.ShowLevels RowLevels:=2
Range("A1").CurrentRegion.SpecialCells(xlCellTypeVisible).Font.Bold = True
'change the header row if necessary
Range(Range("A1"), Range("A1").End(xlToRight)).Font.Italic = True
ActiveSheet.Outline.ShowLevels RowLevels:=3
End Sub
I'm creating automated pivottables from a pivotcache which imports its recordset form an adodb connection.
I need to group the date field and found a way online to do it with the .pivotselect method. The code works fine, however excel does not seem to select the worksheet where the pivottables are somehow, even though the pivottable data is selected. This leads to an error if one select another sheet and then runs the procedure.
Shouldn't pivottable.pivotselect select the sheet also automatically? I have solved it temporarily by having sheets("Pivot").select just before the date grouping code. How may one come around this problem? The current code is based on code generated from macro recorder.
Code
Private Sub PivotAccessADODB()
' Link Pivottable to access database, successfull!
Const ConnectionPath As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\name\Desktop\DataBase.accdb;Persist Security Info=False;"
Dim DataConnection As ADODB.Connection: Set DataConnection = New ADODB.Connection
Dim RecordSet As ADODB.RecordSet: Set RecordSet = New ADODB.RecordSet
DataConnection.ConnectionString = ConnectionPath
DataConnection.Open
Dim SQLString As String: SQLString = "SELECT * FROM ALFA"
With RecordSet
.ActiveConnection = DataConnection
.Source = SQLString
.LockType = adLockReadOnly
.CursorType = adOpenForwardOnly
.Open
End With
' Initiate accept of external data
Dim PTCache As PivotCache
Set PTCache = ActiveWorkbook.PivotCaches.Create(xlExternal)
Set PTCache.RecordSet = RecordSet
'----------------------------------'
'First Pivot Table export procedure
Dim PT As PivotTable: Set PT = PTCache.CreatePivotTable(Sheets("Pivot").Range("A1"), "PivotTable#1")
With PT
.PivotFields("Date").Orientation = xlRowField
.PivotFields("Date").Position = 1
Sheets("pivot").Select ' Bypass selection grouping error, temporary solution as of 2014-12-26
PT.PivotSelect "Date[All]", xlLabelOnly + xlFirstRow, True
Selection.Group Start:=True, End:=True, Periods:=Array(False, False, False, False, True, False, False)
.PivotFields("Adj Close").Orientation = xlDataField
.PivotFields("Sum of Adj Close").Calculation = xlPercentDifferenceFrom
.PivotFields("Sum of Adj Close").BaseItem = "(previous)"
.PivotFields("Volume").Orientation = xlDataField
.PivotFields("Sum of Volume").Calculation = xlPercentDifferenceFrom
.PivotFields("Sum of Volume").BaseItem = "(previous)"
End With
Dim wst As Worksheet: Set wst = Sheets("Mainwindow")
Dim wshape As Shape
Set wshape = wst.Shapes.AddChart2(286, xl3DColumnClustered, wst.Range("A24").Left, wst.Range("A24").Top, _
wst.Range("A24:Q24").Width, wst.Range("A24:A39").Height)
With wshape.Chart
.SetSourceData Source:=PT.TableRange1
.ClearToMatchStyle
.ChartStyle = 291
.ApplyLayout (1)
.ChartTitle.Text = "Difference from previous month in percentage"
.ChartTitle.Format.TextFrame2.TextRange.Font.Size = 14
End With
'-----------------------------------'
'Second Pivot Table export procedure'
'Cleanup
RecordSet.Close
DataConnection.Close
Set RecordSet = Nothing
Set DataConnection = Nothing
End Sub
Be sure to dimension a Worksheet object and set it to the whatever worksheet has the pivot tables:
Dim wkb As Excel.Workheet
Set wkb = ActiveWorkbook.Worksheet("Me")
wkb.Activate 'wkb.Select may give focus but doesn't register as the active worksheet object.
<PT Code>
Set wkb = Nothing
I've spent the last few hours scouring the net for a way to do this without finding a way.
Basically, I have 3 fairly small tables in access that I wish to transfer to an excel workbook on a single worksheet.
I am currently only able to insert these tables onto separate worksheets using the following coding:
DoCmd.TransferSpreadsheet transfertype:=acExport, _
spreadsheettype:=acSpreadsheetTypeExcel12, _
TableName:=DTable, FileName:=strWorksheetPathTable, _
hasfieldnames:=True, _
Range:="Data"
I wish to transfer 2 more tables onto the "Data" worksheet, 1 starting at D1 (table is a single column) and the other at G1.
If anyone could help me out with a push that'd be sweet.
Cheers, Dane I
add microsoft.activex data objects 2.8 to your references
add microsoft office object library to your references
Then create your spreadsheet like this:
dim xl as object: set xl = createobject("Excel.Application")
XL.Visible = False
XL.DisplayAlerts = False
dim wb as object: set wb = xl.Workbooks.Add
dim ws as object: set ws = wb.Worksheets(1)
dim rst as new adodb.recordset
dim r as long, c as long 'row and column
r = 1
c = 1
rst.open "SELECT * FROM Table1", currentproject.connection, adOpenKeyset, adLockReadOnly
if not rst.eof then
ws.range(WS.Cells(r, c).Address).CopyFromRecordSet rst
end if
rst.close
rst.open "SELECT Count(*) FROM Table1", currentproject.connection etc
r = r + rst.fields(1) + 2
rst.Close
rst.open "SELECT * FROM Table2", etc
and so on.
wb.SaveAs FileName:=xlname
xl.Quit
set ws = nothing
set wb = nothing
set xl = nothing
This gives you what you want, with a line or two between each table. You can also now add code into the process to format your spreadsheet how you want if you wish to as well.
If a table needs column headings get them like this:
rst.open "SELECT * FROM Table1", currentproject.connection, adOpenKeyset, adLockReadOnly
dim ii as long
for ii = 0 to rst.fields.count - 1
ws.cells(r, ii + 1) = rst.fields(ii) 'you can offset using c if you want
next
if not rst.eof then
ws.range(WS.Cells(r, c).Address).CopyFromRecordSet rst
end if
I am trying to extract the source data from a PivotTable that uses a PivotTable cache and place it into a blank spreadsheet. I tried the following but it returns an application-defined or object defined error.
ThisWorkbook.Sheets.Add.Cells(1,1).CopyFromRecordset ThisWorkbook.PivotCaches(1).Recordset
Documentation indicates that PivotCache.Recordset is an ADO type, so this ought to work. I do have the ADO library enabled in references.
Any suggestions on how to achieve this?
Unfortunately, there appears to be no way to directly manipulate PivotCache in Excel.
I did find a work around. The following code extracts the the pivot cache for every pivot table found in a workbook, puts it into a new pivot table and creates only one pivot field (to ensure that all rows from the pivot cache are incorporated in the total), and then fires ShowDetail, which creates a new sheet with all of the pivot table's data in.
I would still like to find a way to work directly with PivotCache but this gets the job done.
Public Sub ExtractPivotTableData()
Dim objActiveBook As Workbook
Dim objSheet As Worksheet
Dim objPivotTable As PivotTable
Dim objTempSheet As Worksheet
Dim objTempPivot As PivotTable
If TypeName(Application.Selection) <> "Range" Then
Beep
Exit Sub
ElseIf WorksheetFunction.CountA(Cells) = 0 Then
Beep
Exit Sub
Else
Set objActiveBook = ActiveWorkbook
End If
With Application
.ScreenUpdating = False
.DisplayAlerts = False
End With
For Each objSheet In objActiveBook.Sheets
For Each objPivotTable In objSheet.PivotTables
With objActiveBook.Sheets.Add(, objSheet)
With objPivotTable.PivotCache.CreatePivotTable(.Range("A1"))
.AddDataField .PivotFields(1)
End With
.Range("B2").ShowDetail = True
objActiveBook.Sheets(.Index - 1).Name = "SOURCE DATA FOR SHEET " & objSheet.Index
objActiveBook.Sheets(.Index - 1).Tab.Color = 255
.Delete
End With
Next
Next
With Application
.ScreenUpdating = True
.DisplayAlerts = True
End With
End Sub
Go to the Immediate Window and type
?thisworkbook.PivotCaches(1).QueryType
If you get something other than 7 (xlADORecordset), then the Recordset property does not apply to this type of PivotCache and will return that error.
If you get an error on that line, then your PivotCache is not based on external data at all.
If your source data comes from ThisWorkbook (i.e. Excel data), then you can use
?thisworkbook.PivotCaches(1).SourceData
To create a range object and loop through it.
If your QueryType is 1 (xlODBCQuery), then SourceData will contain the connection string and commandtext for you to create and ADO recordset, like this:
Sub DumpODBCPivotCache()
Dim pc As PivotCache
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Set pc = ThisWorkbook.PivotCaches(1)
Set cn = New ADODB.Connection
cn.Open pc.SourceData(1)
Set rs = cn.Execute(pc.SourceData(2))
Sheet2.Range("a1").CopyFromRecordset rs
rs.Close
cn.Close
Set rs = Nothing
Set cn = Nothing
End Sub
You need the ADO reference, but you said you already have that set.
I found myself having the same problem, needing to scrape programmatically data coming different Excels with cached Pivot data.
Although the topic is a bit old, still looks there is no direct way to access the data.
Below you can find my code, which is a more generalized refinement of the already-posted solution.
The major difference is the filter removal from fields, as sometimes pivot comes with filters on, and if you call .Showdetail it will miss filtered data.
I use it to scrape from different file format without having to open them, it is serving me quite well thus far.
Hope it is useful.
Credit to spreadsheetguru.com on the filter cleaning routine (although I don't remember how much is original and how much is mine to be honest)
Option Explicit
Sub ExtractPivotData(wbFullName As String, Optional wbSheetName As_
String, Optional wbPivotName As String, Optional sOutputName As String, _
Optional sSheetOutputName As String)
' This routine extracts full data from an Excel workbook and saves it to an .xls file.
Dim iPivotSheetCount As Integer
Dim wbPIVOT As Workbook, wbNEW As Workbook, wsPIVOT As Worksheet
Dim wsh As Worksheet, piv As PivotTable, pf As PivotField
Dim sSaveTo As String
Application.DisplayAlerts = False
calcOFF
Set wbPIVOT = Workbooks.Open(wbFullName)
' loop through sheets
For Each wsh In wbPIVOT.Worksheets
' if it is the sheet we want, OR if no sheet specified (in which case loop through all)
If (wsh.name = wbSheetName) Or (wbSheetName = "") Then
For Each piv In wsh.PivotTables
' remove all filters and fields
PivotFieldHandle piv, True, True
' make sure there's at least one (numeric) data field
For Each pf In piv.PivotFields
If pf.DataType = xlNumber Then
piv.AddDataField pf
Exit For
End If
Next pf
' make sure grand totals are in
piv.ColumnGrand = True
piv.RowGrand = True
' get da data
piv.DataBodyRange.Cells(piv.DataBodyRange.Cells.count).ShowDetail = True
' rename data sheet
If sSheetOutputName = "" Then sSheetOutputName = "datadump"
wbPIVOT.Sheets(wsh.Index - 1).name = sSheetOutputName
' move it to new sheet
Set wbNEW = Workbooks.Add
wbPIVOT.Sheets(sSheetOutputName).Move Before:=wbNEW.Sheets(1)
' clean new file
wbNEW.Sheets("Sheet1").Delete
wbNEW.Sheets("Sheet2").Delete
wbNEW.Sheets("Sheet3").Delete
' save it
If sOutputName = "" Then sOutputName = wbFullName
sSaveTo = PathWithSlash(wbPIVOT.path) & FilenameNoExtension(sOutputName) & "_data_" & piv.name & ".xls"
wbNEW.SaveAs sSaveTo
wbNEW.Close
Set wbNEW = Nothing
Next piv
End If
Next wsh
wbPIVOT.Close False
Set wbPIVOT = Nothing
calcON
Application.DisplayAlerts = True
End Sub
Sub PivotFieldHandle(pTable As PivotTable, Optional filterClear As Boolean, Optional fieldRemove As Boolean, Optional field As String)
'PURPOSE: How to clear the Report Filter field
'SOURCE: www.TheSpreadsheetGuru.com
Dim pf As PivotField
Select Case field
Case ""
' no field specified - clear all!
For Each pf In pTable.PivotFields
Debug.Print pf.name
If fieldRemove Then pf.Orientation = xlHidden
If filterClear Then pf.ClearAllFilters
Next pf
Case Else
'Option 1: Clear Out Any Previous Filtering
Set pf = pTable.PivotFields(field)
pf.ClearAllFilters
' Option 2: Show All (remove filtering)
' pf.CurrentPage = "(All)"
End Select
End Sub