my VBA skills aren't the best, if someone could help with the following that would be great.
I have a number of sheets in a workbook that has a date record in the cell range E11:E37.
I'm trying to create a reporting function whereby the user completes a date picker userform, Excel runs a search on the above range in all worksheets in this workbook for a date that falls between the DTPicker1/2 results.
For sheets that return a match, copy all those sheets to a new workbook with name ("Name & current Date".xlsx).
Update: I tried reversing the > and <, no change, think i wrapped in Cdate for the DTPicker Values no results, did both, no results....
Update: code now working but doesnt return a value true where dates in range = 01/06/18 - 14/06/18 where DTP1 = 07/06/18 and DTP2 = 16/06/18. But does return true where DTP1 = 04/06/18 and DTP2 = 08/06/18.
Private Sub CommandButton1_Click()
Dim s As Worksheet, wb As Workbook
For Each s In Worksheets
If CBool(Application.CountIfs(s.Range("E11:E37"), ">" &
CDate(DTPicker1.Value), _
s.Range("E11:E37"), "<" &
CDate(DTPicker2.Value))) Then
If wb Is Nothing Then
s.Copy
Set wb = ActiveWorkbook
Else
s.Copy after:=wb.Worksheets(wb.Worksheets.Count)
End If
End If
Next s
If wb Is Nothing Then
MsgBox ("No Records Found")
Else
wb.SaveAs Filename:="Technicians - Batch Record Report" & Format(Date,
"ddmmyyyy"), _
FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
End If
End Sub
Try this to see if it gets you closer to your goal.
Private Sub CommandButton1_Click()
Dim s As Worksheet, wb as workbook
For Each s In workSheets
If cbool(application.countifs(s.Range("I11:I37"), ">" & cdate(DTPicker1.Value), _
s.Range("I11:I37"), "<" & cdate(DTPicker2.Value))) then
if wb is nothing then
s.copy
set wb = activeworkbook
else
s.copy after:=wb.worksheets(wb.worksheets.count)
end if
end if
next s
if wb is nothing then
MsgBox ("No Records Found")
else
wb.SaveAs Filename:="Technicians - Batch Record Report" & Format(Date, "ddmmyyyy"), _
FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
End If
End Sub
Related
I've been trying to get an easy printout (in PDF using a single button) of one sheet with only active range and one chart located in another sheet. I've got everything working, except after I print, both sheets are grouped together and I can't edit my chart.
I'm trying to make this foolproof and easy for coworkers during real time operations. Right now I can right-click and select 'Ungroup sheets' to fix it, but I hate to have to do that each time (or explain that it needs to be done).
I tried to select a sheet, a different sheet, only one sheet etc. I can't figure out how to get VBA to ungroup the sheets at the end. Any ideas?
Sub CustomPrint()
'if statement to ask for file path
If Dir(Environ("commonprogramfiles") & "\Microsoft Shared\OFFICE" _
& Format(Val(Application.Version), "00") & "\EXP_PDF.DLL") <> "" Then
If FixedFilePathName = "" Then
'Open the GetSaveAsFilename dialog to enter a file name for the PDF file.
FileFormatstr = "PDF Files (*.pdf), *.pdf"
fname = Application.GetSaveAsFilename("", filefilter:=FileFormatstr, _
Title:="Create PDF")
'If you cancel this dialog, exit the function.
If fname = False Then Exit Sub
Else
fname = FixedFilePathName
End If
'Dynamic reference to RT drilling data
Dim LastRow As Long
Dim LastColumn As Long
Dim StartCell As Range
Dim sht As Worksheet
Set sht = Worksheets("rt drilling data")
Set StartCell = Range("A1")
'Refresh UsedRange
Worksheets("rt drilling data").UsedRange
'Find Last Row
LastRow = sht.Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
'Select Range
sht.Range("A1:K" & LastRow).Select
Sheets("Chart Update").Activate
ActiveSheet.ChartObjects(1).Select
ThisWorkbook.Sheets(Array("chart update", "RT drilling data")).Select
ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, _
Filename:=fname, IgnorePrintAreas:=False
'If the export is successful, return the file name.
If Dir(fname) <> "" Then RDB_Create_PDF = fname
End If
If OverwriteIfFileExist = False Then
If Dir(fname) <> "" Then Exit Sub
End If
On Error GoTo 0
Worksheets("ws model updates").Select
End Sub
If Dir(fname) <> "" Then Exit Sub will bypass Worksheets("ws model updates").Select
If OverwriteIfFileExist = False Then
If Dir(fname) <> "" Then
Worksheets("ws model updates").Select
Exit Sub
End If
End If
I have searched everywhere for an answer to this, but I can't find one. how do I check if there is more than 1 worksheet in Workbook.
To get the number of worksheets within an open workbook, something like:
Sub qwerty()
MsgBox "the number of worksheets in this workbook is: " & ThisWorkbook.Worksheets.Count
End Sub
This will exclude Charts, etc.If you have multiple workbooks open, then something like:
MsgBox "the number of worksheets in this workbook is: " & wb.Worksheets.Count
Where you would Set wb in a prior statement.
To run it from Personal.xlsb then Try this
Public Sub Count_Sheets()
Debug.Print "You Have " & Application.Sheets.count & " Sheets " ' Immediate Window
MsgBox "You Have " & Application.Sheets.count & " Sheets "
End Sub
Or use ActiveWorkbook.Sheets.count
This is what ended up working best for me. It incorporates multiple answers in here to do what it does.
Sub CountSheets()
Dim mainWB As Workbook
Dim mainWS As Worksheet
Set mainWB = ActiveWorkbook
Set mainWS = mainWB.Sheets(1)
If mainWB.Sheets.Count > 1 Then MsgBox "There is more than one worksheet in this Excel file."
End Sub
i have a workbook that i use as a template to make estimates that when i'm done filling out the template there is a macro that creates a new workbook and copies all the sheets of the template workbook to the new one and then removes all the formulas and info i don't want the customer to see.
Here's part of my code that creates the new workbook and copies all the sheets from the template to the new one and then cleans it up
Sub TestConvert()
'Disabling the following to speed up the vba code, must re-enable at end of code
ActiveSheet.DisplayPageBreaks = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
Application.DisplayAlerts = False
'adds file name and path to all sheets
Dim WSfn As Worksheet
For Each WSfn In ThisWorkbook.Sheets
'Adds formula to show file path
WSfn.Range("A2") = "=LEFT(CELL(""filename"",RC),FIND(""["",CELL(""filename"",RC),1)-1)"
'Adds formula to show file name
WSfn.Range("A3") = "=MID(CELL(""filename""),FIND(""["",CELL(""filename""))+1,(FIND(""]"",CELL(""filename""))-FIND(""["",CELL(""Filename""))-16))"
WSfn.Calculate 'Calculate sheet
WSfn.Range("A2") = WSfn.Range("A2") 'this will remove the formula from the cell making it text only
WSfn.Range("A3") = WSfn.Range("A3") 'this will remove the formula from the cell making it text only
Next
'************************************************************************************************
'copies all the sheets of the open workbook to a new one
Dim thisWb As Workbook, wbTemp As Workbook
Dim ws As Worksheet
Set thisWb = ThisWorkbook
Set wbTemp = Workbooks.Add 'creates new workbook dimmed as WbTemp
On Error Resume Next 'if there is in error when deleting will not stop the macro from continuing...
'.. deletes the extra sheets 2 sheets if on an older versions of excel
For Each ws In wbTemp.Worksheets
ws.Delete 'deletes all but one sheet in new workbook
Next
On Error GoTo -1 'clears the error handling and sets it to nothing which allows you to create another error trap.
'copys all the sheets from the original to the new workbook dimmed as wbTemp
For Each ws In thisWb.Sheets
ws.Copy After:=wbTemp.Sheets(wbTemp.Worksheets.Count)
Next
wbTemp.Sheets(1).Delete 'deletes the the first sheet in the list in the new workbook which is a black sheet from creating a new workbook
'put vba code to be ran in new book here
'makes all formulas in new workbook values only
wbTemp.Sheets.Select 'selects all sheets in new workbook
Cells.Select 'selects all cell
Selection.Copy 'copies everything selected
Selection.PasteSpecial Paste:=xlPasteValues 'pastes as values only in selected cells
wbTemp.Application.CutCopyMode = False 'clears the clipbored
'removes all defind names from new workbook / submittal
Dim xName As Name
For Each xName In wbTemp.Names
xName.Delete
Next
'removes all dropdowns from new workbook / submittal
Dim DD As Worksheet
For Each DD In wbTemp.Worksheets
Cells.Select
DD.Cells.Validation.Delete
Range("A1").Select
Next
'removes all vba buttons from all sheets
Dim i As Integer
On Error Resume Next
For i = 1 To 1000
wbTemp.Sheets(i).Buttons.Delete
Next i
'All sheets scroll to top left and select "A1"
Dim Sht As Worksheet
'****************************
'change A1 to suit your preference
Const TopLeft As String = "A1"
'****************************
'loop thru all the sheets in the workbook
For Each Sht In Worksheets
'scroll:=True takes cell to the top-left of window
Application.Goto Sheet.Range(TopLeft), scroll:=True
Next
'Hides the following from all sheets
wbTemp.Sheets.Select 'selects all sheets in new workbook
ActiveWindow.DisplayGridlines = False
ActiveWindow.DisplayHeadings = False
'selects the first sheet in the list
Sheets(1).Select
ActiveSheet.DisplayPageBreaks = True
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Application.DisplayAlerts = True
'save vba code here
'works to only add the filename would like it to also open in file path from cell A2
Application.Dialogs(xlDialogSaveAs).Show Range("A3").Text & "- (Submittal) " & Format(Date, "mm-dd-yy") & "_" & Format(Time, "hhmm") & ".xlsx"
End Sub
im wanting to make it so when the save window opens it opens in the file path from cell A2 and populates the filename from cell A3
i can also send/post the full excel file if that helps any.
The Application.GetSaveAsFilename method is a good choice for this. Pass the return value to a variant type var so you can test for Cancel or Close.
Dim sFN As Variant
With Worksheets("Sheet6")
sFN = .Range("A1") & Chr(92) & .Range("A2") & Format(Date, "_mm-dd-yy") '<~~ no extension yet
End With
With Application
sFN = .GetSaveAsFilename(InitialFileName:=sFN, _
FileFilter:="Excel Workbook (*.xlsx), *.xlsx," & _
"Macro Workbook (*.xlsm), *.xlsm," & _
"Binary Workbook (*.xlsb), *.xlsb")
End With
Select Case sFN
Case False
'user clicked Cancel or Close (×)
Debug.Print sFN
Case Else
With ThisWorkbook
Select Case Right(sFN, 5)
Case ".xlsx"
.SaveAs Filename:=sFN, FileFormat:=xlOpenXMLWorkbook
Case ".xlsm"
.SaveAs Filename:=sFN, FileFormat:=xlOpenXMLWorkbookMacroEnabled
Case ".xlsb"
.SaveAs Filename:=sFN, FileFormat:=xlExcel12
Case Else
'there really shouldn't be a case else
End Select
End With
End Select
I've added a Select Case statement statement for a Workbook.SaveAs method to three msot common types of Excel workbooks.
You can use the .InitialFileName property of the dialog.
Dim ws As Excel.Worksheet
Set ws = ActiveWorkbook.Sheets("Sheet1")
Dim oFileDialog As FileDialog
Set oFileDialog = Application.FileDialog(msoFileDialogSaveAs)
With oFileDialog
.Title = "Save File"
.ButtonName = "Ok"
.InitialFileName = ws.Range("A2").Value & "\" & ws.Range("A3").Value
.Show
End With
If you need to get back the name that it was saved as you can use .SelectedItems after .Show
MsgBox (oFileDialog.SelectedItems(1))
NOTE:
You probably want to do a quick verification that the directory in A2 exists before doing this. If it does not exist it will throw this into some users folder.
EDIT I'm not sure why yours isn't saving, could be excel version or some other variable in your code.
Since you have the path and name, do you really need the saveas dialog? You could just do
Workbooks.Add
'Then your code in your template that is modifying the active workbook
'Then save it without the dialog
ActiveWorkbook.SaveAs ws.Range("A2").Value & "\" & ws.Range("A3").Value
'OR
ActiveWorkbook.SaveAs Filename:= ws.Range("A2").Value & "\" & ws.Range("A3").Value
I am fairly new with Excel vba but have been using access vba for some time now.
I have some code which splits a main file into several other files based on a distinct column in excel
Sub SplitbyValue()
Dim FromR As Range, ToR As Range, All As Range, Header As Range
Dim Wb As Workbook
Dim Ws As Worksheet
'Get the header in this sheet
Set Header = Range("D8").EntireRow
'Visit each used cell in column D, except the header
Set FromR = Range("D9")
For Each ToR In Range(FromR, Range("D" & Rows.Count).End(xlUp).Offset(1))
'Did the value change?
If FromR <> ToR Then
'Yes, get the cells between
Set All = Range(FromR, ToR.Offset(-1)).EntireRow
'Make a new file
Set Wb = Workbooks.Add(xlWBATWorksheet)
'Copy the data into there
With Wb.ActiveSheet
Header.Copy .Range("A8")
All.Copy .Range("A9")
End With
'Save it
Wb.SaveAs ThisWorkbook.Path & "\" & Format(Date, "yyyy.mm.dd") & _
" - " & FromR.Value & ".xls", xlWorkbookNormal
Wb.Close
'Remember the start of this section
Set FromR = ToR
End If
Next
End Sub
This works great for the main sheet, but have to copy multiple tabs and this only captures one sheet. How can I expand this so it copies the other sheets as well into that file?
example:
ColumnA
Id1
Id2
Id3
This creates three files (Id1)(Id2)(Id3) but ignores the other sheets.
Create an encompassing loop and define the worksheet being processed with a With...End With statement. You loop through a For Each...Next Statement using a Worksheet object on the Worksheets collection but I typically use the index of each worksheet.
Sub SplitbyValue()
Dim FromR As Range, ToR As Range, dta As Range, hdr As Range
Dim w As Long, ws As Worksheet, wb As Workbook, nuwb As Workbook
'Get the header in this sheet
Set wb = ActiveWorkbook
For w = 1 To wb.Worksheets.Count
With wb.Worksheets(w)
Set hdr = .Range(.Cells(8, "D"), .Cells(8, Columns.Count).End(xlToLeft))
'Visit each used cell in column D, except the header
Set FromR = .Range("D9")
For Each ToR In .Range(FromR, .Range("D" & Rows.Count).End(xlUp).Offset(1))
'Did the value change?
If FromR <> ToR Then
'Yes, get the cells between
Set dta = .Range(FromR, ToR.Offset(-1)).EntireRow
'Make a new file
Set nuwb = Workbooks.Add(xlWBATWorksheet)
'Copy the data into there
With nuwb.Sheet1
hdr.Copy .Range("A8")
dta.Copy .Range("A9")
End With
'Save it
nuwb.SaveAs ThisWorkbook.Path & "\" & Format(Date, "yyyy.mm.dd") & _
" - " & FromR.Value & ".xls", xlWorkbookNormal
nuwb.Close False
Set nuwb = Nothing
'Remember the start of this section
Set FromR = ToR
End If
Next ToR
End With
Next w
End Sub
I did not set up a full test environment but this should get you heading in the right direction. I've always found it unreliable to depend on ActiveSheet.
Here is a function that will allow you to search for a sheet and goto it by name.
Private Sub loopsheets(strSheetName As String)
iFoundWorksheet = 0
For iIndex = 1 To ea.ActiveWorkbook.Worksheets.Count
Set ws = ea.Worksheets(iIndex)
If UCase(ws.Name) = UCase(strSheetName) Then
iFoundWorksheet = iIndex
Exit For
End If
Next iIndex
If iFoundWorksheet = 0 Then
MsgBox "No worksheet was found with the name RESULTS (this is not case sensetive). Aborting."
End If
Set ws = ea.Worksheets(iFoundWorksheet)
ws.Activate
End Sub
If you want to just loop them all you just need the for loop.
Dim iIndex as Integer
For iIndex = 1 To ea.ActiveWorkbook.Worksheets.Count
Set ws = ea.Worksheets(iIndex)
ws.Activate
'Call your code here.
SplitbyValue
Next iIndex
I am trying to come up with code that will make copies of all the worksheets in a given workbook. Seems simple enough, right? A little Google searching and I cobbled together the following code:
Sub Commandbutton1_click()
Dim Cnt As Long
Dim i As Long
Dim Sht1 As String
Dim MyChoice As String
Dim MyFile As String
Dim CurrWorkBook As Excel.Workbook
Dim Month As String
'Instructional message box
MsgBox "When the 'Open' dialog appears, select the workbook containing the worksheets you want to split and then click Ok."
'Get file name
With Application.FileDialog(msoFileDialogFilePicker)
.AllowMultiSelect = False
.Show
MyChoice = .SelectedItems(1)
End With
Application.ScreenUpdating = False
MyFile = Dir(MyChoice)
Set CurrWorkBook = Workbooks.Open(Filename:=MyFile)
CurrWorkBook.Activate
Cnt = Sheets.Count
InputMsg = "Enter the month of the EOM Budget Review:"
InputTitle = "Month"
Month = InputBox(InputMsg, InputTitle)
For i = 1 To Cnt Step 1
Sht1 = Sheets(i).Name
Sheets(Array(Sht1)).Copy
ActiveWorkbook.SaveAs Filename:=Sht1 & " - " & Month & " EOM Budget Review.xlsx", _
FileFormat:=51, Password:="", WriteResPassword:="", _
ReadOnlyRecommended:=False, CreateBackup:=False
ActiveWorkbook.Close
Next i
CurrWorkBook.Save
CurrWorkBook.Close
Application.ScreenUpdating = True
End Sub
It works perfectly...except when it doesn't. In some workbooks, it will copy every sheet with no difficulty. In some workbooks, it will copy some of the sheets, but throw the "Copy method of Sheets class failed" unless you have it skip certain sheets. I have not been able to figure out what the sheets it will not copy have in common. Is there some way I can improve this code? Are there certain features of worksheets that will cause this kind of code to fail inevitably?
Solved thanks to Alex P.'s comment above. I copied the following code from another forum:
Sub UnhideAll()
Dim WS As Worksheet
For Each WS In Worksheets
WS.Visible = True
Next
End Sub
Then I used Call UnhideAll right after Application.ScreenUpdating = False. I also used CurrWorkBook.Close savechanges:=False at the end so that the workbook being copied would not be saved and its hidden worksheets would go back to being hidden.