Save slicer values to worksheet - excel

Hi I having difficulty trying to cycle through the slicers to see if they are filtered or not.
My goal is to get all the selected Slicer into a worksheet so that I can apply a (High to Low) filter to the underlying pivot data so that I can pick the "Top 5 over budget" based upon the selections made in the Data Slicers.
I have the following code but get see error: Run Time Error 438’ Object doesn’t support this method
Can someone advise how I can achieve this.
Public Sub top_over_under_booked()
Dim oSi As SlicerItem
Dim oSlicercache As SlicerCache
Dim oSl As SlicerCacheLevel
Dim oPt As PivotTable
Dim oSh As Worksheet
Set target_ws = ThisWorkbook.Worksheets("Get Slicer Selections")
For Each oSlicercache In ThisWorkbook.SlicerCaches
For Each oPt In oSlicercache.PivotTables
oPt.Parent.Activate 'Slice Name
worksheet_name = UCase(oPt.Parent.Name)
If worksheet_name = UCase("Chart Analysis 5 Years") Then
column_no = 0
slicer_name = UCase(oSlicercache.Name)
Select Case UCase(oSlicercache.Name)
Case Is = "SLICER_FY1"
column_no = 1
Case Is = "SLicer_REPORT_PT_DEPT1"
column_no = 2
'There are actually loads more slicer which needs to ne ignored.
End Select
If column_no <> 0 Then
For Each oSl In ActiveWorkbook.SlicerCaches(oSlicercache.Name) ' <----- Error
For Each oSi In oSl.SlicerItems
'oSi.Selected = True
check_slicer_string = oSi.Value
'target_ws.Cells(ource_ws.Cells(65000, column_no).End(xlUp).Row + 1, column_no) = oSlicercache.Value
Next
Next
End If
oPT.Parent.Name
End If
Next
Next
End Sub

there are two different Excel's
using Microsoft.Office.Tools.Excel;
using Excel = Microsoft.Office.Interop.Excel;
EXAMPLE within ThisWorkBook.cs
public string SelectedReportCategories()
{
var selection = "";
var myTarget = this;
try
{
var caches = myTarget.SlicerCaches["Slicer_REPORT"];
foreach (Excel.SlicerItem slicerItem in caches.SlicerItems)
{
if (slicerItem.Selected)
selection = selection + " " + slicerItem.Name;
}
}
catch (Exception e)
{
ShowError("Configuration", (e.InnerException != null) ? e.InnerException.Message : e.Message);
}
return selection;
}

Related

How to get PO with each SIZE/EAN breakdown on ITEM level?

QUESTION
I'm using VBA for retrieving data from SAP via BAPI. What RFC should I use, and how, to retrieve PO details at the "each SIZE for each ITEM" level.
EXAMPLE
In this screenshot you see that the PO includes 3 ITEMs. Each of these ITEMs includes several SIZEs/EANs. And for each of the SIZEs/EANs, the specific QUANTITIES are indicated
I want to retrieve this data into Excel. So I create all the needed objects for working with SAP, connect to BAPI_PO_GETITEMS, fill in PURCHASEORDER-parameter, indicate the table PO_ITEMS:
Option Explicit
Public Functions As SAPFunctionsOCX.SAPFunctions
Private LogonControl As SAPLogonCtrl.SAPLogonControl
Private objConnection As SAPLogonCtrl.Connection
Dim Func As SAPFunctionsOCX.Function
Public eNUMBER_OF_ENTRIES As SAPFunctionsOCX.Parameter
Public tENTRIES As SAPTableFactoryCtrl.Table
Public TableFactory As SAPTableFactory
Sub BAPI_PO_GETDETAIL()
Dim i As Integer, j As Integer
Dim retcd As Boolean
Dim SilentLogon As Boolean
Set LogonControl = CreateObject("SAP.LogonControl.1")
Set Functions = CreateObject("SAP.Functions")
Set TableFactory = CreateObject("SAP.TableFactory.1")
Set objConnection = LogonControl.NewConnection
SilentLogon = True
'Use the below block to hardcode system connection and connect automatically
objConnection.Client = ""
objConnection.ApplicationServer = ""
objConnection.Language = ""
objConnection.User = ""
objConnection.Password = ""
objConnection.System = ""
objConnection.SystemNumber = ""
'Logging into SAP
If objConnection.Logon(0, SilentLogon) Then
'Logon was successful
MsgBox "Logged on!"
'Create an object to call the RFC FM
Functions.Connection = objConnection
'Actual FM is added here
Set Func = Functions.Add("BAPI_PO_GETITEMS")
'Populate the importing parameters
Func.Exports("PURCHASEORDER").Value = "2845158864"
'Indicate the TABLE needed
Set tENTRIES = Func.Tables("PO_ITEMS")
'Call FM
Func.Call
'Dump onto the worksheet
For i = 1 To tENTRIES.ColumnCount 'cells(R, C)
cells(1, i).Value = tENTRIES.ColumnName(i)
Next i
For i = 1 To tENTRIES.RowCount
For j = 1 To tENTRIES.ColumnCount
cells(i + 1, j).Value = tENTRIES.Value(i, j)
Next j
Next i
Else
MsgBox "Not Logged on"
End If
End Sub
and get only 3 rows - for each of the 3 ITEMS, without the breakdown by SIZE/EAN:
How to retrieve the breakdown by SIZE/EAN, like on this screenshot:

Exporting multiple datagridviews to different tabs of excelsheet

I'm a newbie to visual studio.
I want to export different datagridviews from multiple forms to an excel workbook as different sheets on the same workbook based on whether it is checked in checkedlist box.
Basically I am doing a daily checklist for our school on location basis where the user can export checklist floor wise on the corresponding form of each floor, but also can export a multiple sheet workbook containing diff floors as per its checked in checklistbox, any help please? I am stuck at checkedlistbox. currently i am doing as below: but gives me an exception at the second sheet.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim excel As Microsoft.Office.Interop.Excel._Application = New Microsoft.Office.Interop.Excel.Application()
Dim workbook As Microsoft.Office.Interop.Excel._Workbook = excel.Workbooks.Add(Type.Missing)
Dim worksheet As Microsoft.Office.Interop.Excel._Worksheet = Nothing
Me.Cursor = Cursors.WaitCursor
Dim sheetnumber As Integer = 1
If CheckedListBox1.GetItemChecked(0) = True Then
worksheet = workbook.Sheets(sheetnumber)
sheetnumber = sheetnumber + 1
worksheet.Name = "Anim_Check List_"
Dim cellRowIndex As Integer = 1
Dim cellColumnIndex As Integer = 1
For i As Integer = 0 To Form7.DataGridView1.Rows.Count - 1
For j As Integer = 0 To Form7.DataGridView1.Columns.Count - 1
If cellRowIndex = 1 Then
worksheet.Cells(cellRowIndex, cellColumnIndex) = Form7.DataGridView1.Columns(j).HeaderText
Else
worksheet.Cells(cellRowIndex, cellColumnIndex) = Form7.DataGridView1.Rows(i).Cells(j).Value.ToString()
End If
cellColumnIndex += 1
Next
cellColumnIndex = 1
cellRowIndex += 1
Next
End If
If CheckedListBox1.GetItemChecked(1) = True Then
workbook.Worksheets.Add(sheetnumber)
excel.Worksheets(sheetnumber).activate
sheetnumber = sheetnumber + 1
worksheet.Name = "Edits 1-5_"
Dim cellRowIndex As Integer = 1
Dim cellColumnIndex As Integer = 1
For i As Integer = 0 To Form8.DataGridView1.Rows.Count - 1
For j As Integer = 0 To Form8.DataGridView1.Columns.Count - 1
If cellRowIndex = 1 Then
worksheet.Cells(cellRowIndex, cellColumnIndex) = Form8.DataGridView1.Columns(j).HeaderText
Else
worksheet.Cells(cellRowIndex, cellColumnIndex) = Form8.DataGridView1.Rows(i).Cells(j).Value.ToString()
End If
cellColumnIndex += 1
Next
cellColumnIndex = 1
cellRowIndex += 1
Next
End If
Dim saveDialog As New SaveFileDialog()
saveDialog.FileName = workbook.Name
saveDialog.Filter = "Excel files (*.xlsx)|*.xlsx|All files (*.*)|*.*"
saveDialog.FilterIndex = 1
If saveDialog.ShowDialog() = System.Windows.Forms.DialogResult.OK Then
workbook.SaveAs(saveDialog.FileName)
MessageBox.Show("Export Successful")
End If
End Sub
It is very difficult to understand what you are trying to do. From what I can decipher, there appears to be three (3) different WindowsForms open. The main active form has a Button and a CheckedListBox. The two other forms (Form7, Form8) each have a DataGridView with some data.
I assume that the CheckListBox allows the user to select which form to use when exporting to Excel. Example, if the user checks the first option, then clicks the button, then the DataGridView on Form7 will be exported to the Excel workbook. If the second option is checked then Form8’s DataGridView will be exported to the same workbook.
I hope I have this correct. To help, I would recommend you break the problem down into smaller pieces. Example, looking at the code in both “if” statements that check for a checked state in the checked list box… it is clear they are doing the same thing. The only difference is the DataGridView and the name of the worksheet.
It looks like a method, that took a workbook to add the sheet to, a DataGridView to export and finally a string for the worksheet name… might come in handy.
Private Sub AddGridToWorkbook(workbook As Workbook, dgv As DataGridView, sheetName As String)
This method would add a new worksheet to the given workbook using the given sheetName as the name for the new worksheet. Lastly the method would loop through the given DataGridView and export the values to the new worksheet.
The current posted code is trying to print the header row inside the loop through the grids rows. This will miss the first row of data. The header row for the new excel worksheet needs to be exported separately and outside the loop through the grids rows.
Lastly, I am curious what Form7 and Form8 are… If these are WindowsForm “Classes”… then the statement:…
worksheet.Cells(cellRowIndex, cellColumnIndex) = Form7.DataGridView1.Rows(i).Cells(j).Value.ToString()
This will not work as you expect… Form7 is a “Class” and you are using it like an instantiated object.
In my example below, I have two WindowsForms “Classes” called “Form7” and “Form8”. When the main form loads, I instantiate and show these two forms. Example: create the global variable forms.
Dim form7 As Form7 = New Form7()
Dim form8 As Form8 = New Form8()
Then show the forms on load.
form7.Show()
form8.Show()
Now the previous line of code will work using the instantiated “Form7” object named form7.
worksheet.Cells(cellRowIndex, cellColumnIndex) = form7.DataGridView1.Rows(i).Cells(j).Value.ToString()
Revised code to export the grids
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
excel.Visible = True
Dim workbook = excel.Workbooks.Add()
If CheckedListBox1.GetItemChecked(0) = True Then
AddGridToWorkbook(workbook, form7.DataGridView1, "Anim_Check List_")
End If
If CheckedListBox1.GetItemChecked(1) = True Then
AddGridToWorkbook(workbook, form8.DataGridView1, "Edits 1-5_")
End If
Dim saveDialog As New SaveFileDialog()
saveDialog.FileName = workbook.Name
saveDialog.Filter = "Excel files (*.xlsx)|*.xlsx|All files (*.*)|*.*"
saveDialog.FilterIndex = 1
If saveDialog.ShowDialog() = System.Windows.Forms.DialogResult.OK Then
workbook.SaveAs(saveDialog.FileName)
MessageBox.Show("Export Successful")
End If
End Sub
Private Sub AddGridToWorkbook(workbook As Workbook, dgv As DataGridView, sheetName As String)
Try
Dim worksheet As Worksheet = workbook.Worksheets.Add()
worksheet.Name = sheetName
AddHeaderRow(worksheet, dgv)
For row As Integer = 0 To dgv.Rows.Count - 1
For col As Integer = 0 To dgv.Columns.Count - 1
If dgv.Rows(row).Cells(col).Value IsNot Nothing Then
worksheet.Cells(row + 2, col + 1) = dgv.Rows(row).Cells(col).Value.ToString()
End If
Next
Next
Catch ex As Exception
MessageBox.Show("Ex: " + ex.Message)
End Try
End Sub
Private Sub AddHeaderRow(worksheet As Worksheet, dgv As DataGridView)
For col As Integer = 0 To dgv.Columns.Count - 1
worksheet.Cells(1, col + 1) = dgv.Columns(col).HeaderText
Next
End Sub
Hope this helps

Search Title In Access DataBase

Background:
I need to open an Access file and get the information there to make a comparison with the data in my Excel spreadsheet.
I'm using Microsoft Office 15.0 Access db engine Object library instead of Microsoft DAO object library.
Problem:
While I'm available to paste all the data with the following code, for some reason, it starts in "row 2" ignoring titles.
Sub Sample()
Const PathToDB = "C:\...\AccessFile.accdb"
Const TitleSampleTable = "Sample Table"
Dim BDSample As Database
Dim SampleTable As Recordset
Dim SampleTableDef As TableDef
Dim CounterTitles As Long
Dim CounterRows As Long
Dim ColToPasteIn As Long
Dim RowToPasteIn As Long
Set BDSample = DBEngine.Workspaces(0).OpenDatabase(PathToDB)
Set SampleTable = BDSample.OpenRecordset(TitleSampleTable, dbOpenDynaset)
Set SampleTableDef = BDSample.TableDefs(TitleSampleTable)
For CounterTitles = 0 To SampleTableDef.RecordCount
RowToPasteIn = RowToPasteIn + 1
ColToPasteIn = 1
For CounterRows = 0 To SampleTable.Fields.Count
With Sheets(TitleSampleTable)
.Cells(RowToPasteIn, ColToPasteIn).Value = SampleTable.Fields(CounterRows) 'this is starts in the "body" of access, I can't figure a way to retrieve titles!
ColToPasteIn = ColToPasteIn + 1
End With
Next CounterRows
SampleTable.MoveNext
Next CounterTitles
Set BDSample = Nothing
Set SampleTable = Nothing
Set SampleTableDef = Nothing
End Sub
Sample data in Accesss
Sample Data in Excel
Questions:
How do I get the titles values?
You can get the field names and populate the row 1
For i = 0 To SampleTable.Fields.Count - 1
Sheets(TitleSampleTable).Cells(1, i + 1) = SampleTable.Fields(i).Name
Next i
And then you can populate the date from row 2 onward as you were originally doing

How to transfer multiple Data in one excel Workbook to another excel workbook

I am hoping you could help me, make a Code for an Update button. I wanted to have a 1 workbook -Enter Data, that when I feel up the workbook, and click the update button, it will automatically update specific workbook, base on the workbook file. mentioned in the EnterData Workbook.
Eg. I want to Make EnterData with following Details.
ItemName:
Item Quantity:
Department: 3 Department per month
Sheet Name: Month
FileName: Depends on the ItemName
and once I click the update button, it will automatically update the specific file with the specific sheet name and department
Hope you could help me with this.
This will get you a good head start
I try to divide the work to be performed into simple, readable, and logical task.
Use Constants for settings such as: Root Directories, Cell References, Column References
I want to see this in the top of a module
Public Const TartgetWorkBookName As String = "C:\Users\SomeFolder\Data.xlsm"
Public Const TartgetWorkSheetName As String = "Sheet3"
Public Const TartgetTopLeftCellAddress As String = "A1"
Versus this somewhere buried in code:
Dim TargetWorkBook As Workbook
Set TargetWorkBook = Application.Workbooks.Open("C:\Users\SomeFolder\Data.xlsm")
Set getTargetR1C1 = TargetWorkBook.Worksheets("Sheet3").Range("A1")
Here is a rough draft of a basic pattern that I follow. It is a working example.
Option Explicit
Const TartgetWorkBookName As String = "C:\Users\SomeFolder\Data.xlsm"
Const TartgetWorkSheetName As String = "Sheet3"
Const TartgetTopLeftCellAddress As String = "A1"
Dim TargetWorkBook As Workbook
Set TargetWorkBook = Application.Workbooks.Open(TartgetWorkBookName)
Set getTargetR1C1 = TargetWorkBook.Worksheets(TartgetWorkSheetName).Range(TartgetTopLeftCellAddress)
Sub PostRecord()
Dim TargetR1C1 As Range, ItemName As String, Qty As Double, Department As String, Month_ As Integer
Set TargetR1C1 = getTargetR1C1()
'If your transfering a lot of data turn off
Speedboost True
'------Begin Loop
'------For x = 2 to LastColumn
'------Set Variables
ItemName = "Dragon Sauce"
Qty = 3
Department = "Spicy Hot Stuff"
Month_ = Month(Date)
'------Post Varibles to taget
UpdateRecord TargetR1C1, ItemName, Qty, Department, Month_
'Next
'Turn Everything back on
Speedboost False
End Sub
Sub UpdateRecord(TargetR1C1 As Range, ItemName As String, Qty As Double, Department As String, Month_ As Integer)
Dim c As Range
Dim x As Long, y As Long
If Len(TargetR1C1.Offset(1)) Then
x = TargetR1C1.End(xlDown).Row + 1
Else
x = TargetR1C1.Rows + 1
End If
y = TargetR1C1.Column
Set c = TargetR1C1.Cells
c(x, y) = ItemName
c(x, y + 1) = Qty
c(x, y + 2) = Department
c(x, y + 3) = Month_
End Sub
Sub Speedboost(bSpeedUpMacros As Boolean)
With Application
.ScreenUpdating = Not (bSpeedUpMacros)
.EnableEvents = Not (bSpeedUpMacros)
If bSpeedUpMacros Then
.Calculation = xlCalculationManual
Else
.Calculation = xlCalculationAutomatic
End If
End With
End Sub
Function getTargetR1C1() As Range
Dim TargetWorkBook As Workbook
Set TargetWorkBook = Application.Workbooks.Open(TartgetWorkBookName)
Set getTargetR1C1 = TargetWorkBook.Worksheets(TartgetWorkSheetName).Range(TartgetTopLeftCellAddress)
End Function

When reading down a column of Excel file, how to define cell coordinates without selecting a cell?

Can anyone tell me how to improve this macro?
All the macro does is it just reads an Excel file for a list a accounts to update in an application (SmarTerm Beta). It technically already accomplishes the goal, but is there a way to code it so that while it’s reading the Excel file, the coordinates of the cells from which to read the account numbers and also the coordinates of the cells in which to write an output don’t depend on a "pre-selected" a cell? The risk with selecting a cell is that if someone were to accidentally select a different cell while the macro is running, everything will get screwed up.
Here's my current code:
Public oExcelObj As Object
Function WaitSystem(Optional NoDialog as Variant) As Boolean
Dim nContinue as Integer
Dim nTimeOut as Integer 'In seconds.
'The default timeout for each command is 3 minutes.
'Increase this value if your host requires more time
'for each command.
nTimeOut = 10
If IsMissing(NoDialog) then NoDialog = False
'Wait for response from host.
Session.EventWait.Timeout = nTimeOut
Session.EventWait.EventType = smlPAGERECEIVED
Session.EventWait.MaxEventCount = 1
WaitSystem = True
If Session.EventWait.Start = smlWAITTIMEOUT Then
If NoDialog Then
WaitSystem = False
Else
nContinue = QuerySyncError()
If nContinue <> ebYes then WaitSystem = False
End If
End If
Set LockStep = Nothing
End Function
'Establish link. Search for Excel.
Function OleLinkConnection
Const XlMaximized = &HFFFFEFD7
Titlebar$ = AppFind$("Microsoft Excel")
If Titlebar$ <> "" Then
bIsExcelActive = True
If AppGetState(Titlebar$) = ebMinimized Then
AppSetState 2, Titlebar$
End If
Else
bIsExcelActive = False
End If
If bIsExcelActive Then
'Create Excel Object using current instance of Excel.
Set oExcelObj = GetObject(, "Excel.Application")
Else
'Create Excel Object using a new instance of Excel.
Set oExcelObj = CreateObject("Excel.Application")
End If
Version = oExcelObj.Application.Version
oExcelObj.ScreenUpdating = True
oExcelObj.Displayalerts = True
oExcelObj.Visible = true
End Function
Sub JPBmacro
Dim AccountNumber As String
Dim Temp As Integer
Begin Dialog StartDialogTemplate ,,211,74,"Run JPBmacro?"
OKButton 60,12,92,20,.Proceed
CancelButton 60,40,92,20,.Exit
End Dialog
Dim StartDialog As StartDialogTemplate
r% = Dialog(StartDialog)
If r% = 0 Then End
g$ = "G:\DATA\outputfile.xlsx"
oleCode = OleLinkConnection
oExcelObj.Workbooks.Open g$
oExcelObj.Range("A1").Select ‘<----This selects the cell from which all coordinates are based off of. The coordinates of oExcelObj.ActiveCell.Offset(Y,X).Value VBA depend on selecting a cell.
NEXTACCOUNT:
Temp = 0
AccountNumber = oExcelObj.ActiveCell.Offset(Temp,0).Value
While AccountNumber <> ""
Session.SendKey "CLEAR"
If WaitSystem = False Then End
Session.Send "ACTU " & AccountNumber
Session.SendKey "ENTER"
If WaitSystem = False Then End
If Trim(Session.ScreenText(4,6,1,22)) = "INVALID ACCOUNT NUMBER" Or Trim(Session.ScreenText(4,6,1,19)) = "ACCOUNT NOT ON FILE" Then
oExcelObj.ActiveCell.Offset(Temp,1).Value = Trim(Session.ScreenText(4,6,1,22))
GoTo RESTARTLOOP
End If
UPDATEIOV:
If Trim(Session.ScreenText(13,76,1,1)) = "Y" Then
oExcelObj.ActiveCell.Offset(Temp,1).Value = "Account already flagged as institutional."
Else
Session.Row = 13
Session.Column = 76
Session.send "Y"
Session.SendKey "ENTER"
If WaitSystem = False Then End
oExcelObj.ActiveCell.Offset(Temp,1).Value = Trim(Session.ScreenText(24,2,1,50))
End If
RESTARTLOOP:
Temp = Temp + 1
AccountNumber = oExcelObj.ActiveCell.Offset(Temp,0).Value
Wend
ENDNOW:
oExcelObj.Workbooks.Close
MsgBox "All Done!"
End Sub
Why not keep the reference to the first cell?
Dim rng as Range
Set rng = oExcelObj.Range("A1")
i=1
...
x = rng.Cell(i,1).Value
'Or faster yet is reading all the values into an variant array.
Dim array() as Variant
array = rng.Resize(N,M).Value
' Work with array as
x = array(i,1)
Given the comment from assylias and that another poster has since "answered" with this approach:
I can't see where oExcelObj is instantiated? Or how you are referring to a specific sheet.
Regardless of which,
you can avoid select by setting a range, ie Set rng1 = oExcelObj.Sheets(1).Range("A1")
and then use offsets from rng1.
The user won't be able to interfere while the code is running

Resources