using VBA to hide rows in a pivot table

gayjaybird

New Member
Joined
Aug 6, 2007
Messages
39
Code:
Sub Hidesingles()
  For i = 5 To ActiveSheet.UsedRange.Rows.Count
      For c = 3 To ActiveSheet.UsedRange.Column.Count
        If Cells(i, c) <= 1 Then Cells(i, 1).EntireRow.Hidden = True Else: Next c
        End If
Next i
End Sub

I'm trying to filter a pivot table with VBA. The spreadsheet/database I'm summarizing has fields for the store name, the package tracking number, the date and the sender's store name. Row headings are store name and tracking number, and the columns are the date. The pivot table counts how many times a particular sender's store name shows up on a particular date. I have the rows collapsed so that the table only displays the subtotals for each store for each day. How can I filter the table so that only the stores who sent more than one package a day are listed? I tried the code above and ended up with a 'Next without For error.' Any ideas?
 
By the way, I think you'd find the original pivot table you worked with much easier with counts in rows, so going back to the original post (5 yards up), you could do as follows without adding any fields to the data:
20071001_packages.xls
ABCDE
1
2
3CountofSenderCompanyName
4Reference1PickupDateTotal
5StoreA#15583020071
6StoreA#18383020071
7StoreA#18583020071
8StoreA#215382920071
9StoreA#232582220071
10StoreB#101682820072
11StoreB#5182220071
12GrandTotal8
Sheet4


This leaves the 2 standing out quite clearly, don't you think..Now your original idea of hiding rows with a macro is also applicable...although including a row field for tracking numbers will still throw it off. You could create some kind of alternate test here to pursue that further...
 
Upvote 0

Excel Facts

When they said...
When they said you are going to "Excel at life", they meant you "will be doing Excel your whole life".
BUT>>>
If I were you I would add the column mentioned above, with the extra column for counting package per day...

And just autofilter it with "custom" criteria of greater than 1...This could also be coded so you can run it with a button, etc. No pivot tables!

Wouldn't that be just too easy?

Play around with what we have so far and let me know if anything looks worth sticking with.
Regards.
 
Upvote 0
Actually the coding sounds great! One thing I notice though is that the counting array formula you gave earlier allows the pivot table to filter correctly, but when I simply try to filter the raw data, the maximum value I get for count is '1'. I'm not sure why the extra cells throw it off, but they do. Is there a way to dynamically count the 'raw data, and then copy the relevant fields to a separate worksheet for further manipulation/analysis? We've been condensing 369 pages of raw data by hand, which gets rather tedious and time consuming.

Thanks!
 
Upvote 0
Alright...back to square 2 :lol:

I am working with your raw data and assuming there are more columns that what we've been showing in our posts...so I've used Constants that you will need to change, all at the top of the code window. If Pickup Date is in Column C, this is going to be a value of 3 for COLUMN_PICKUP_DATE, and if it is in Column D, then value is 4...right? You just tell Excel what columns the important data is in. You also need to tell it what row your headers are in, which I've always had in Row 1 so far.

I also assume good, clean data without blanks and extraneous stuff in cells below or to the right. Just a data table.

This code will create the array formula, so all you need to do is run it...formula is created to the right and is placed in a column called "Count". The results are output to a new excel file, and only the rows of relevant shipments. (I think I spent an hour working this formula in VB...trying to get the R1C1 right...ugh).

I think it is fairly logical but probably we'll find a bug :-D Let me know how it works. I've deleted the count in the export because this is really not useful data anymore--if you sum it up its not a real count, because the total duplicates on every row (I'll study a few Aladin Akyurek posts and see if I can figure out a formula for a running total :pray: ).

I didn't have the same problem filtering that you describe so I am assuming that with this code you'll find it works properly - I do use an autofilter but it is all created in code and the tests work on this end just fine. You see the autofilter on the sheet when the code ends and if you click the down arrow on the count field and click on custom you should see my custom filter criteria there. If filtering is still giving you trouble we can rewrite the code without a filter, and just loop through the rows on by one to catch the relevant rows.

:!: Again, change the constants for the correct relative columns and rows, and do not put the array formula in yourself. (But if you do you can just delete the line of code that is a call to the createArray routine)

We'll see if this works...nothing to waste but some evening candles here.

Code:
'----------------------------------------------
'Enter these constant values for your sheet setup
'Example: Column "C" is 3
Const COLUMN_SENDER_COMPANY_NAME As Integer = 4
Const COLUMN_PICKUP_DATE As Integer = 3
Const ROW_WITH_HEADERS As Integer = 1
'----------------------------------------------
Sub FilterForExcessShipments()
Dim lRow As Long
Dim lCol As Long
Dim wb As Workbook

Set wb = Workbooks.Add
ThisWorkbook.Activate

'Get last Row
lRow = Cells(Rows.Count, 1).End(xlUp).Row
lCol = Cells(ROW_WITH_HEADERS, Columns.Count).End(xlToLeft).Column

'Create Array Formula in column to right of data
'This line cound be deleted if the formula was always there already
Call CreateArrayFormulaInColumnToRight(lRow, lCol)

'Autofilter
'Variable lCol assumes the array formula is in the last column
Range(Cells(ROW_WITH_HEADERS, 1), Cells(lRow, lCol)).AutoFilter _
    Field:=lCol, Criteria1:=">1", Operator:=xlAnd

'copy to new workbook
Cells(ROW_WITH_HEADERS, 1).CurrentRegion.SpecialCells(xlCellTypeVisible).Copy
wb.Sheets(1).Paste
Application.CutCopyMode = False
'Delete array formula
With wb.Sheets(1)
    For x = 1 To .Cells(1, Columns.Count).End(xlToLeft).Column
        If UCase(.Cells(1, x).Value) = "COUNT" Then
            .Cells(1, x).EntireColumn.Delete
            Exit For
        End If
    Next x
End With

End Sub
'----------------------------------------------
Private Sub CreateArrayFormulaInColumnToRight(ByVal lRow As Long, ByRef lCol As Long)
Dim strMyFormula As String
Dim colSender As Integer
Dim colDate As Integer
Dim rHeaders As Integer

'Just in case
AutoFilterMode = False

'to make it easier to read the formula
colSender = COLUMN_SENDER_COMPANY_NAME
colDate = COLUMN_PICKUP_DATE
rHeaders = ROW_WITH_HEADERS

'Code enters array formula in empty column to the right
'this column will be called "COUNT"
'Header
Cells(rHeaders, lCol + 1).Value = "COUNT"
'Formula
strMyFormula = "=SUM((R" & rHeaders + 1 & "C" & colDate & ":" _
    & "R" & lRow & "C" & colDate & "=" & "R" & "C[" & -1 * (lCol + 1 - colDate) & "])" _
    & "*" & _
    "(R" & rHeaders + 1 & "C" & colSender & ":" & _
    "R" & lRow & "C" & colSender & "=" & "R" & "C[" & -1 * (lCol + 1 - colSender) & "])" & _
    "*1)"
'Debug
Debug.Print "=SUM((R2C3:R24C3=RC[-2])*(R2C4:R24C4=RC[-1])*1)"
Debug.Print strMyFormula
'Enter formulas
Cells(rHeaders + 1, lCol + 1).FormulaArray = strMyFormula
Cells(rHeaders + 1, lCol + 1).Copy Destination:=Range(Cells(rHeaders + 2, lCol + 1), Cells(lRow, lCol + 1))

'reset lCol
lCol = Cells(ROW_WITH_HEADERS, Columns.Count).End(xlToLeft).Column

End Sub

Edit: added divider lines to subs for easier viewing here on the board.
 
Upvote 0
Nota Bene: I've had just a tad of trouble "resetting" so best to run the formula on a fresh copy of the data, or at least to make sure you un-autofilter and clear the last column that was added by code.

We can always re-think this but here you *should* have both a filtered table of your raw data and a second set of copied rows that are only the relevant stores, with their shipments for days when they shipped more than one. This is either an end or a starting point...depends on your needs.

Regards.
 
Upvote 0
Ok. So far so good. I think it would work best to have the unfiltered data on one worksheet, and then the filtered data on a second sheet. Is there a way to hide the extraneous columns/fields? I have fields in column A through column BJ (BK if you count the 'count' column for the macro) That's a total of 56(57) columns. When filtered, I only need columns/fields G, W, Y, AC, and AG--Tracking Number, Pickup Date, Sender Company Name, Sender Zip, and Receiver City, respectively. So that would be hide every column except columns 7, 23, 25,29, and 33. These are the columns I need in the filtered report:
Marilyns report.xls
ABCDEFGH
1TrackingNumberPickupDateSenderCompanyNameSenderZipActualPickupDateAcct#ChgAmtReceiverCity
Sheet1


Thanks again!

Note: the 3 extra columns: Actual Pickup date, Acct # and Chg Amt, will be filled in by the user.
 
Upvote 0
Okay...here's a new try (I am really starting to regret we aren't doing this with Microsoft Access...not that this isn't fun but we could probably have whipped up a simple SQL query in about 5 minutes without any VBA at all!).

I've simply built on the existing code and added new routines. Changes include - hiding columns, deleting any old Count columns (at the end on the right), adding three rows after "Sender Zip" (only on the new sheet) and a lot more data checking ... because of course as I test the code I get all kinds of bugs from my own re-processing of data.

The output is now in the same relative row as the source file. Again, use the constants at the top of the module to tell Excel where the data is. I tried moving some columns around and my code seems to work wherever I put the columns, although in reality you will probably have a stable data set that isn't moving around.

It hides row based on the values in the headers (which really drove me just about crazy but I guess the problem was with copy data from this board...so it should be fine in excel)...see this thread for the story:
http://www.mrexcel.com/board2/viewtopic.php?p=1423864#1423864

So...

(There's a sub called Test that deletes the new added workbooks without saving them and then runs the main routine)

Edit: I also added Option Explicit so if you edit this code yourself and add new variables they must be Dimmed.

Code:
Option Explicit
'----------------------------------------------
'Enter these constant values for your sheet setup
'Example: Column "C" is 3
Const COLUMN_SENDER_COMPANY_NAME As Integer = 4
Const COLUMN_PICKUP_DATE As Integer = 3
Const ROW_WITH_HEADERS As Integer = 1
'----------------------------------------------
Sub FilterForExcessShipments()
Dim lRow As Long
Dim lCol As Long
Dim wb As Workbook
Dim wsSource As Worksheet
Dim x As Long

'References to sheets and ensure no hidden columns or autofilters
Set wsSource = ActiveSheet
Set wb = Workbooks.Add
wsSource.Activate
wsSource.AutoFilterMode = False
wsSource.Columns.Hidden = False


'Get last Row
lRow = Cells(Rows.Count, 1).End(xlUp).Row
lCol = Cells(ROW_WITH_HEADERS, Columns.Count).End(xlToLeft).Column

'Remove Prior Count Column if it exists (if we ran this before)
If Cells(ROW_WITH_HEADERS, lCol).Value = "COUNT" Then
    Cells(ROW_WITH_HEADERS, lCol).EntireColumn.Delete
    lCol = Cells(ROW_WITH_HEADERS, Columns.Count).End(xlToLeft).Column
End If

'Create Array Formula in column to right of data
'This line cound be deleted if the formula was always there already
Call CreateArrayFormulaInColumnToRight(lRow, lCol)

'Autofilter
'Variable lCol assumes the array formula is in the last column
Range(Cells(ROW_WITH_HEADERS, 1), Cells(lRow, lCol)).AutoFilter _
    Field:=lCol, Criteria1:=">1", Operator:=xlAnd

'copy to new workbook (on row 1)
Cells(ROW_WITH_HEADERS, 1).CurrentRegion.SpecialCells(xlCellTypeVisible).Copy
wb.Sheets(1).Activate
Cells(ROW_WITH_HEADERS, 1).PasteSpecial
Application.CutCopyMode = False
'Delete array formula
With wb.Sheets(1)
    For x = 1 To .Cells(ROW_WITH_HEADERS, Columns.Count).End(xlToLeft).Column
        If UCase(.Cells(ROW_WITH_HEADERS, x).Value) = "COUNT" Then
            .Cells(ROW_WITH_HEADERS, x).EntireColumn.Delete
            Exit For
        End If
    Next x
End With

'Hide columns and add new columns to newly created sheet
Call TakeOutColumns(wb, wb.Sheets(1), True)
Call TakeOutColumns(ActiveWorkbook, wsSource, False)

'Clean up new workbook
Call MyColumnWidths(wb.Sheets(1))

wsSource.Activate

End Sub
'----------------------------------------------
Private Sub CreateArrayFormulaInColumnToRight(ByVal lRow As Long, ByRef lCol As Long)
Dim strMyFormula As String
Dim colSender As Integer
Dim colDate As Integer
Dim rHeaders As Integer

'Just in case
ActiveSheet.AutoFilterMode = False

'to make it easier to read the formula
colSender = COLUMN_SENDER_COMPANY_NAME
colDate = COLUMN_PICKUP_DATE
rHeaders = ROW_WITH_HEADERS

'Code enters array formula in empty column to the right
'this column will be called "COUNT"
'Header
Cells(rHeaders, lCol + 1).Value = "COUNT"
'Formula
strMyFormula = "=SUM((R" & rHeaders + 1 & "C" & colDate & ":" _
    & "R" & lRow & "C" & colDate & "=" & "R" & "C[" & -1 * (lCol + 1 - colDate) & "])" _
    & "*" & _
    "(R" & rHeaders + 1 & "C" & colSender & ":" & _
    "R" & lRow & "C" & colSender & "=" & "R" & "C[" & -1 * (lCol + 1 - colSender) & "])" & _
    "*1)"
'Debug
Debug.Print "=SUM((R2C3:R24C3=RC[-2])*(R2C4:R24C4=RC[-1])*1)"
Debug.Print strMyFormula
'Enter formulas
Cells(rHeaders + 1, lCol + 1).FormulaArray = strMyFormula
Cells(rHeaders + 1, lCol + 1).Copy Destination:=Range(Cells(rHeaders + 2, lCol + 1), Cells(lRow, lCol + 1))

'reset lCol
lCol = Cells(ROW_WITH_HEADERS, Columns.Count).End(xlToLeft).Column

End Sub
'----------------------------------------------
Private Sub TakeOutColumns(ByRef Arg1 As Workbook, ByRef Arg2 As Worksheet, _
        ByVal Arg3 As Boolean)
Dim ws As Worksheet
Dim lCol As Long
Dim strTest As String
Dim x As Long
Dim y As Byte
Dim myArray(1 To 3)

'Reference calling sheet and activate sheet for this routine
Set ws = ActiveSheet
Arg1.Activate
Arg2.Activate

'New column headers to be added
myArray(1) = "Chg Amt"
myArray(2) = "Acct #"
myArray(3) = "Actual Pickup Date"

If Arg3 = True Then
    'To add new columns for user to fill in later
    'Adds three columns to the right of "Sender Zip"
    lCol = Cells(ROW_WITH_HEADERS, Columns.Count).End(xlToLeft).Column
    For x = lCol To 1 Step -1
        If UCase(Cells(ROW_WITH_HEADERS, x).Value) = "SENDER ZIP" Then
            For y = 1 To 3
                Columns(x + 1).Insert Shift:=xlToRight
                Cells(ROW_WITH_HEADERS, x + 1).Value = myArray(y)
            Next y
        End If
    Next x
End If

'To hide columns that are to be hidden
lCol = Cells(ROW_WITH_HEADERS, Columns.Count).End(xlToLeft).Column
For x = lCol To 1 Step -1
    
    Select Case Trim(UCase(CStr(Cells(ROW_WITH_HEADERS, x).Value)))
 
        Case Is = "TRACKING NUMBER", "PICKUP DATE", "SENDER COMPANY NAME", _
                "SENDER ZIP", "RECEIVER CITY", "CHG AMT", "ACCT #", "ACTUAL PICKUP DATE"
        Case Else
            Columns(x).Hidden = True
        
    End Select

Next x

'Return to calling sheet
ws.Activate

End Sub
'----------------------------------------------
Private Sub MyColumnWidths(ByRef Arg1 As Worksheet)
Dim lCol As Long
Dim x As Long
Dim ws As Worksheet

Set ws = ActiveSheet

Arg1.Activate
Columns.AutoFit
lCol = Cells(ROW_WITH_HEADERS, Columns.Count).End(xlToLeft).Column
For x = lCol To 1 Step -1
    If Columns(x).ColumnWidth < 10 Then
        Columns(x).ColumnWidth = 10
    End If
Next x
Cells(ROW_WITH_HEADERS, 1).Activate
Application.CutCopyMode = False

ws.Activate
End Sub
'----------------------------------------------
Sub Test()
Dim wb As Workbook
Dim ans As Integer
Dim msg As String

msg = "This sub deletes all open workbooks with names like Book1, Book2, etc." & vbCrLf & vbCrLf
msg = msg & "Continue?"
ans = MsgBox(msg, vbOKCancel)
If ans <> vbOK Then End

For Each wb In Workbooks
    If Left(wb.Name, 4) = "Book" Then
        wb.Close SaveChanges:=False
    End If
Next wb

Call FilterForExcessShipments
End Sub
 
Upvote 0
Ok, so that works great. Now is there a way to copy the filtered values so that they are no longer an array and can be sorted, deleted and otherwise manipulated by an end user? They'd also like subtotals for each Store based on the visible values to help break up the report.

Thank for working with all these fiddly changes!

Edit: PS I told the person this would have been easier in Access, but they dug in their heels.
 
Upvote 0
Now is there a way to copy the filtered values so that they are no longer an array and can be sorted, deleted and otherwise manipulated by an end user?

I may be losing you on this one - I probably have a different definition of "array" here. Generally, I think that with the output of the above macro, you have two sheets, one which is "all" data but filtered, and the other which is "excess shipments" data. You could take the output on either sheet and do with it as you please. The filtered data could be copied to a new sheet and pasted - you'd get only the visible data if you did that. Or use the other sheet.

can be sorted, deleted and otherwise manipulated by an end user? They'd also like subtotals for each Store based on the visible values to help break up the report
I have added a routine to the code to copy the sheet of data to a second sheet "ForSubtotals" - despite my comments above. So now you have three sheets! I am not familiar with subtotaling code so I didn't want to chance it - I wasn't sure how to get the subtotal fields correct for where you want group and sum, and still keep the routine from being hardcoded. So you'll have to do the subtotals "by hand". If you need the original data with all the columns (from the filtered sheet), you can copy the cells and paste them onto a new sheet, then subtotal. I tried to code that in but found it was really slow so maybe we can code that only if you really need it.

In the new routine there is a constant you can set to true or false depending on whether you want the second output sheet in a new book by itself or in the same workbook as the second output sheet.

Hope this helps. Its a lot the same as what you already have, I guess.

Code:
Option Explicit
'----------------------------------------------
'Enter these constant values for your sheet setup
'Example: Column "C" is 3
Const COLUMN_SENDER_COMPANY_NAME As Integer = 4
Const COLUMN_PICKUP_DATE As Integer = 3
Const ROW_WITH_HEADERS As Integer = 1
'----------------------------------------------
Sub FilterForExcessShipments()
Dim lRow As Long
Dim lCol As Long
Dim wb As Workbook
Dim wsSource As Worksheet
Dim x As Long

'References to sheets and ensure no hidden columns or autofilters
Set wsSource = Activesheet
Set wb = Workbooks.Add
wb.Sheets(1).Name = "StoreList"
wsSource.Activate
wsSource.AutoFilterMode = False
wsSource.Columns.Hidden = False

'Get last Row
lRow = Cells(Rows.Count, 1).End(xlUp).Row
lCol = Cells(ROW_WITH_HEADERS, Columns.Count).End(xlToLeft).Column

'Remove Prior Count Column if it exists (if we ran this before)
If Cells(ROW_WITH_HEADERS, lCol).Value = "COUNT" Then
    Cells(ROW_WITH_HEADERS, lCol).EntireColumn.Delete
    lCol = Cells(ROW_WITH_HEADERS, Columns.Count).End(xlToLeft).Column
End If

'Create Array Formula in column to right of data
'This line cound be deleted if the formula was always there already
Call CreateArrayFormulaInColumnToRight(lRow, lCol)

'Autofilter
'Variable lCol assumes the array formula is in the last column
Range(Cells(ROW_WITH_HEADERS, 1), Cells(lRow, lCol)).AutoFilter _
    Field:=lCol, Criteria1:=">1", Operator:=xlAnd

'copy to new workbook (on row 1)
Cells(ROW_WITH_HEADERS, 1).CurrentRegion.SpecialCells(xlCellTypeVisible).Copy
wb.Sheets(1).Activate
Cells(ROW_WITH_HEADERS, 1).PasteSpecial
Application.CutCopyMode = False
'Delete array formula
With wb.Sheets(1)
    For x = 1 To .Cells(ROW_WITH_HEADERS, Columns.Count).End(xlToLeft).Column
        If UCase(.Cells(ROW_WITH_HEADERS, x).Value) = "COUNT" Then
            .Cells(ROW_WITH_HEADERS, x).EntireColumn.Delete
            Exit For
        End If
    Next x
End With

'Hide columns and add new columns to newly created sheet
Call TakeOutColumns(wb, wb.Sheets(1), True)
Call TakeOutColumns(ActiveWorkbook, wsSource, False)

'Clean up new workbook
Call MyColumnWidths(wb.Sheets(1))

wsSource.Activate

Call NewSheetWithSubtotals(wb.Sheets(1))

wsSource.Activate

Application.CutCopyMode = False

End Sub
'----------------------------------------------
Private Sub CreateArrayFormulaInColumnToRight(ByVal lRow As Long, ByRef lCol As Long)
Dim strMyFormula As String
Dim colSender As Integer
Dim colDate As Integer
Dim rHeaders As Integer

'Just in case
Activesheet.AutoFilterMode = False

'to make it easier to read the formula
colSender = COLUMN_SENDER_COMPANY_NAME
colDate = COLUMN_PICKUP_DATE
rHeaders = ROW_WITH_HEADERS

'Code enters array formula in empty column to the right
'this column will be called "COUNT"
'Header
Cells(rHeaders, lCol + 1).Value = "COUNT"
'Formula
strMyFormula = "=SUM((R" & rHeaders + 1 & "C" & colDate & ":" _
    & "R" & lRow & "C" & colDate & "=" & "R" & "C[" & -1 * (lCol + 1 - colDate) & "])" _
    & "*" & _
    "(R" & rHeaders + 1 & "C" & colSender & ":" & _
    "R" & lRow & "C" & colSender & "=" & "R" & "C[" & -1 * (lCol + 1 - colSender) & "])" & _
    "*1)"
'Debug
Debug.Print "=SUM((R2C3:R24C3=RC[-2])*(R2C4:R24C4=RC[-1])*1)"
Debug.Print strMyFormula
'Enter formulas
Cells(rHeaders + 1, lCol + 1).FormulaArray = strMyFormula
Cells(rHeaders + 1, lCol + 1).Copy Destination:=Range(Cells(rHeaders + 2, lCol + 1), Cells(lRow, lCol + 1))

'reset lCol
lCol = Cells(ROW_WITH_HEADERS, Columns.Count).End(xlToLeft).Column

End Sub
'----------------------------------------------
Private Sub TakeOutColumns(ByRef Arg1 As Workbook, ByRef Arg2 As Worksheet, _
        ByVal Arg3 As Boolean)
Dim ws As Worksheet
Dim lCol As Long
Dim strTest As String
Dim x As Long
Dim y As Byte
Dim myArray(1 To 3)

'Reference calling sheet and activate sheet for this routine
Set ws = Activesheet
Arg1.Activate
Arg2.Activate

'New column headers to be added
myArray(1) = "Chg Amt"
myArray(2) = "Acct #"
myArray(3) = "Actual Pickup Date"

If Arg3 = True Then
    'To add new columns for user to fill in later
    'Adds three columns to the right of "Sender Zip"
    lCol = Cells(ROW_WITH_HEADERS, Columns.Count).End(xlToLeft).Column
    For x = lCol To 1 Step -1
        If UCase(Cells(ROW_WITH_HEADERS, x).Value) = "SENDER ZIP" Then
            For y = 1 To 3
                Columns(x + 1).Insert Shift:=xlToRight
                Cells(ROW_WITH_HEADERS, x + 1).Value = myArray(y)
            Next y
        End If
    Next x
End If

'To hide columns that are to be hidden
lCol = Cells(ROW_WITH_HEADERS, Columns.Count).End(xlToLeft).Column
For x = lCol To 1 Step -1
    
    Select Case Trim(UCase(CStr(Cells(ROW_WITH_HEADERS, x).Value)))
  
        Case Is = "TRACKING NUMBER", "PICKUP DATE", "SENDER COMPANY NAME", _
                "SENDER ZIP", "RECEIVER CITY", "CHG AMT", "ACCT #", "ACTUAL PICKUP DATE"
        Case Else
            Columns(x).Hidden = True
        
    End Select

Next x

'Return to calling sheet
ws.Activate

End Sub
'----------------------------------------------
Private Sub MyColumnWidths(ByRef Arg1 As Worksheet)
Dim lCol As Long
Dim x As Long
Dim ws As Worksheet

Set ws = Activesheet

Arg1.Activate
Columns.AutoFit
lCol = Cells(ROW_WITH_HEADERS, Columns.Count).End(xlToLeft).Column
For x = lCol To 1 Step -1
    If Columns(x).ColumnWidth < 10 Then
        Columns(x).ColumnWidth = 10
    End If
Next x
Cells(ROW_WITH_HEADERS, 1).Activate
Application.CutCopyMode = False

ws.Activate
End Sub
'----------------------------------------------
Private Sub NewSheetWithSubtotals(Arg1 As Worksheet)
Dim x As Long
Const IN_A_NEW_WORKBOOK As Boolean = True
    'Set the above constant equal to false if you want a second subtotals sheet
        'in the same workbook instead of in a new workbook

Arg1.Activate

If IN_A_NEW_WORKBOOK Then
    Arg1.Copy
    Activesheet.Name = "ForSubtotals"
Else
    Arg1.Copy After:=Arg1
    Activesheet.Name = "ForSubtotals"
End If

'Since we are working off the sheet with the columns added, take them back out
For x = Cells(ROW_WITH_HEADERS, Columns.Count).End(xlToLeft).Column To 1 Step -1
    If WorksheetFunction.CountA(Columns(x)) = 1 Then
        Columns(x).Delete
    End If
Next x

'Sort by Sender company
Cells(ROW_WITH_HEADERS, COLUMN_SENDER_COMPANY_NAME).CurrentRegion.Sort _
    Key1:=Cells(ROW_WITH_HEADERS, COLUMN_SENDER_COMPANY_NAME), Order1:=xlAscending, Header:=xlGuess

End Sub
'----------------------------------------------
Sub MyTestMyFilterForExcessShipments()
Dim wb As Workbook
Dim ans As Integer
Dim msg As String

msg = "This sub deletes all open workbooks with names like Book1, Book2, etc." & vbCrLf & vbCrLf
msg = msg & "Continue?"
ans = MsgBox(msg, vbOKCancel)
If ans <> vbOK Then End

For Each wb In Workbooks
    If Left(wb.Name, 4) = "Book" Then
        wb.Close SaveChanges:=False
    End If
Next wb

Call FilterForExcessShipments
End Sub
'----------------------------------------------
Sub MyTestMyNewSheetsWithSubtotals()
Dim ws As Worksheet
Dim xRay As Worksheet
Dim x As Integer

x = 1
Set xRay = Activesheet

For Each ws In Worksheets
    If ws.Name = "Subtotals" Then
        ws.Name = ws.Name & Format(Now, "_Hh_Nn_Ss")
    End If
Next ws

xRay.Activate
Call NewSheetWithSubtotals(xRay)
End Sub
[/quote]
 
Upvote 0
I may be losing you on this one - I probably have a different definition of "array" here. Generally, I think that with the output of the above macro, you have two sheets, one which is "all" data but filtered, and the other which is "excess shipments" data. You could take the output on either sheet and do with it as you please. The filtered data could be copied to a new sheet and pasted - you'd get only the visible data if you did that. Or use the other sheet.
. . . snip. . .

I have added a routine to the code to copy the sheet of data to a second sheet "ForSubtotals" - despite my comments above. So now you have three sheets! I am not familiar with subtotaling code so I didn't want to chance it - I wasn't sure how to get the subtotal fields correct for where you want group and sum, and still keep the routine from being hardcoded. So you'll have to do the subtotals "by hand". If you need the original data with all the columns (from the filtered sheet), you can copy the cells and paste them onto a new sheet, then subtotal. I tried to code that in but found it was really slow so maybe we can code that only if you really need it.

In the new routine there is a constant you can set to true or false depending on whether you want the second output sheet in a new book by itself or in the same workbook as the second output sheet.

Ok. So if I'm understanding correctly, after we get the output, we need to copy the visible data to a new sheet. Right now when I try to edit the filtered report it tells me I cannot change part of the array. Basically, I'm just trying to get this macro to the point that my relatively-excel illiterate user can open up the file, run a macro and Voila! It's ready for her to do her thing. In the copied data, just for readability, she'd like a subtotal for each store counting the total excess shipments. If this is not doable because of hard coding, I understand.

Thanks for all of your help!
 
Upvote 0

Forum statistics

Threads
1,225,471
Messages
6,185,172
Members
453,281
Latest member
shantor

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top