i'm actually trying to, for a command button, set a print area based on colomn A (if A is empty then this row is last row. and when the print area is set, just print it out with landscape layout. My code for now is as follow. When i clic it prints but doesn't update the print area can you help me plz
Private Sub Imprimer_Click()
ActiveSheet.Unprotect Password:="mypass"
Dim usedRangeEx As Range
Set usedRangeEx = GetUsedRangeIncludingCharts(ActiveSheet)
usedRangeEx.Activate
Debug.Print usedRangeEx.Address
ActiveSheet.Protect Password:="mypass"
End Sub
Private Function GetUsedRangeIncludingCharts(target As Worksheet) As Range
ActiveSheet.Unprotect Password:="mypass"
Dim firstRow As Long
Dim firstColumn As Integer
Dim lastRow As Long
Dim lastColumn As Integer
Dim oneChart As ChartObject
For Each cell In Range("A5:A65")
If Not IsEmpty(cell) Then
lastRow = cell.Row
End If
Next
With target
firstRow = .UsedRange.cells(1).Row
firstColumn = .UsedRange.cells(1).Column
lastColumn = .UsedRange(.UsedRange.cells.Count).Column
Set GetUsedRangeIncludingCharts = .Range(.cells(firstRow, firstColumn), _
.cells(lastRow, lastColumn))
End With
ThisWorkbook.ActiveSheet.PrintOut
With ActiveSheet.PageSetup
.Zoom = False
.FitToPagesTall = 1
.FitToPagesWide = 1
End With
ActiveSheet.Protect Password:="mypass"
End Function
Set your print area
Sub Button1_Click()
Dim LstRw As Long, PrnG As Range
LstRw = Cells(Rows.Count, "A").End(xlUp).Row
Set PrnG = Range("A1:C" & LstRw) ' or whatever column you want
ActiveSheet.PageSetup.PrintArea = PrnG.Address
End Sub
Related
I have written a small code that allow me to:
in a defined range (xrng) in column F, find all the cells that contain certain text and once found, select all the cells in the range A:G on the same row and delete them. I have a reverse loop, which work partially, as ignores some cells in the range, specifically the 2nd and the 3rd. Below a before and after pic:
Here my code:
Sub removeapp()
Dim g As Long, xrng As Range, lastrow As Long, i As Long
i = 4
lastrow = Cells(Rows.Count, "F").End(xlUp).Row
Set xrng = Range(Cells(lastrow, "F"), Cells(i, "F"))
For g = xrng.Count To i Step -1
If xrng.Cells(g).Value = "Adjustment" Or xrng.Cells(g).Value = "Approved" Then
Range(Cells(xrng.Cells(g).Row(), "A"), Cells(xrng.Cells(g).Row(), "G")).Delete
End If
Next
End Sub
Could you help me to figure out why?
Also, the code runs really slow... if you have any tip to make it slighlty faster would be great!
Try this, please:
Sub removeappOrig()
Dim xrng As Range, lastrow As Long, sh As Worksheet
Set sh = ActiveSheet 'good to put here your real sheet
lastrow = sh.Cells(sh.Rows.count, "F").End(xlUp).Row
Set xrng = sh.Range("A4:F" & lastrow)
xrng.AutoFilter field:=6, Criteria1:="=Adjustment", Operator:=xlOr, _
Criteria2:="=Approved", VisibleDropDown:=False
Application.DisplayAlerts = False
xrng.SpecialCells(xlCellTypeVisible).Delete
Application.DisplayAlerts = True
sh.AutoFilterMode = False
End Sub
The next code is also fast enough since it iterates between array elements (in memory), not deletes row by row (it creates a ranges Union) and delete all at once:
Private Sub remoRangesAtOnce()
Dim i As Long, lastRow As Long, sh As Worksheet
Dim arrF As Variant, rng As Range, rngDel As Range
Set sh = ActiveSheet 'please name it according to your sheet name
lastRow = sh.Cells(sh.Rows.count, "F").End(xlUp).Row
Set rng = sh.Range("F4:F" & lastRow)
arrF = rng.Value
For i = LBound(arrF) To UBound(arrF)
If arrF(i, 1) = "Adjustment" Or arrF(i, 1) = "Approved" Then
If rngDel Is Nothing Then
Set rngDel = sh.Range(sh.Range("A" & i + 3), sh.Range("F" & i + 3))
Else
Set rngDel = Union(rngDel, sh.Range(sh.Range("A" & i + 3), sh.Range("F" & i + 3)))
End If
End If
Next i
If Not rngDel Is Nothing Then rngDel.Delete xlShiftUp
End Sub
I am new to writing macros and trying to write one for work. Below is a piece of code I have been fighting with. I want it to look at sheet "NG304" and find key words listed in column B. If the key words are there, move them to the second spreadsheet "Payroll Detail". Issues i'm having - the code is not going through the whole list and it doesn't seem to be pasting in the next available row on the payroll detail spreadsheet (it will simply paste on top of my header).
Code:
Dim Findme As String, Findwhat As String, c As Range
With ActiveWorkbook.Worksheets("NG304")
For Each c In .Range(.Cells(2, "B"), .Cells(Rows.Count, "B").End(xlUp))
Findwhat = vbNullString
Findme = StrConv(c.Value2, vbProperCase)
Select Case True
Case Findme Like "VCIP"
Findwhat = "VCIP"
Case Findme Like "Company Labor"
Findwhat = UCase(Findme)
Case Else
'do nothing
End Select
If CBool(Len(Findwhat)) Then
With .Parent.Worksheets("NG304")
c.EntireRow.Cut Destination:=Worksheets("Payroll Detail").Range("A" & lastrow + 1)
lastrow = lastrow + 1
End With
End If
Next c
End With
This will filter each value defined in K_WORDS (at the top), and move the rows to the other sheet:
Option Explicit
Public Sub moveKeywordRows()
Const K_WORDS As String = "VCIP,Company Labor" '<------- Defined keywords
Dim wsFrom As Worksheet, wsDest As Worksheet, kw As Variant, i As Long, lr As Long
Set wsFrom = ThisWorkbook.Worksheets("NG304")
Set wsDest = ThisWorkbook.Worksheets("Payroll Detail")
kw = Split(K_WORDS, ",")
Application.ScreenUpdating = False
For i = 0 To UBound(kw)
lr = wsDest.Cells(wsDest.Rows.Count, "B").End(xlUp).Row
With wsFrom.UsedRange
.AutoFilter Field:=2, Criteria1:="=" & kw(i)
.Copy
wsDest.Cells(lr, "A").PasteSpecial xlPasteAll
.SpecialCells(xlCellTypeVisible).EntireRow.Delete
End With
Application.CutCopyMode = False
wsDest.Activate: wsDest.Cells(1, "A").Select
Next
wsDest.UsedRange.EntireColumn.AutoFit
With wsFrom
.Activate 'wsFrom.UsedRange.AutoFilter '.ShowAllData
End With
Application.ScreenUpdating = True
End Sub
This is your posted code, with some adjustments - it seems to be working:
Public Sub moveKeywordRows1()
Dim FindMe As String, FindWhat As String, c As Range, lr As Long, wsDest As Worksheet
Set wsDest = ThisWorkbook.Worksheets("Payroll Detail")
With ThisWorkbook.Worksheets("NG304")
Application.ScreenUpdating = False
For Each c In .Range(.Cells(2, "B"), .Cells(.Rows.Count, "B").End(xlUp))
FindMe = StrConv(c.Value2, vbProperCase)
FindWhat = vbNullString
Select Case UCase(FindMe)
Case "VCIP": FindWhat = "VCIP"
Case UCase("Company Labor"): FindWhat = "Company Labor"
End Select
If Len(FindWhat) > 0 Then
c.EntireRow.Cut Destination:=wsDest.Range("A" & lr + 1)
lr = lr + 1
End If
Next
Application.ScreenUpdating = True
End With
End Sub
I have the below code. The code will go into each of the 17 workbooks and extract certain columns based on the columns headers name. This will repeat and add to the bottom of the master workbook, until the last one has been extracted.
Unfortunately, if there is nothing in one of the columns on one of the individual 17 workbooks, the data from the next workbook gets moved up in the cells. Is there anyway to sort this. I have added the code below.
Option Explicit
Sub CopyColumns()
Dim CopyFromPath As String, FileName As String
Dim CopyToWb As Workbook, wb As Workbook, CopyToWs As Worksheet
Dim lastRow As Long, NextRow As Long, lcol As Long, c As Long, sv As Integer
Dim ws As Worksheet
Dim myCol As Long
Dim myHeader As Range
r\"
Set CopyToWb = ActiveWorkbook
Set c).End(xlUp).Row
If lastRow = 1 Then GoTo nxt
Range(Cells(2, c), Cells(lastRow, c)).Copy
CopyToWs.Activate
Set myHeader = CopyToWs.Rows(1).Find(What:=.Cells(1, c).Value, Lookat:=xlWhole)
With CopyToWs
If Not myHeader Is Nothing Then
myCol = myHeader.Column
NextRow = .Cells(Rows.Count, myCol).End(xlUp).Row + 1
.Cells(NextRow, myCol).PasteSpecial xlPasteValues
Application.CutCopyMode = False
Set myHeader = Nothing
End If
nxt:
End With
End If
Next c
wb.Close saveChanges:=False
End With
FileName = Dir
Loop
Application.ScreenUpdating = True
End Sub
Thank you in advance
Calculate NextRow only once per workbook, and then use it for all columns:
Do While Len(FileName) > 0
'Calculate the next row to be populated for all columns, based on the last
'used cell in column A
'(I used column A, but pick whatever destination column will always be
'populated in every workbook.)
With CopyToWs
NextRow = .Cells(.Rows.Count, "A").End(xlUp).Row + 1
End With
'Process this workbook
Set wb = Workbooks.Open(CopyFromPath & FileName)
With wb.Sheets("Open Issue Actions")
lcol = .Cells(1, .Columns.Count).End(xlToLeft).Column
For c = 1 To lcol
'...
With CopyToWs
If Not myHeader Is Nothing Then
myCol = myHeader.Column
'NextRow = .Cells(Rows.Count, myCol).End(xlUp).Row + 1
.Cells(NextRow, myCol).PasteSpecial xlPasteValues
Application.CutCopyMode = False
Set myHeader = Nothing
End If
End With
nxt:
'...
Actually you want one row per sheet. Nothing else. Nothing more. You do not even need to calculate it. You need to increment it lngRow = lngRow+1.
Try to use the following into your code:
Option Explicit
Sub CopyColumns()
Dim lngRow As Long: lngRow = 1
Do While Len(FileName) > 0
Set wb = Workbooks.Open(CopyFromPath & FileName)
With wb.Sheets("Open Issue Actions")
lngRow = lngRow + 1
With CopyToWs
If Not myHeader Is Nothing Then
myCol = myHeader.Column
.Cells(lngRow, myCol).PasteSpecial xlPasteValues
Set myHeader = Nothing
End If
End With
End With
wb.Close saveChanges:=False
Loop
Application.ScreenUpdating = True
End Sub
In the code you add/edit three things:
The line Dim lngRow as Long: lngRow=1 on top with the other Dim
lngRow = lngRow + 1 after the With wb.Sheets("Open Issue Actions")
the paste values should be like this .Cells(lngRow, myCol).PasteSpecial xlPasteValues
The whole code is here: https://pastebin.com/kXdzkGZ1
The idea is to have lngRow and to increment it for every WorkSheet that you open. And do not do anything else with it.
In general, your code can be optimized in some ways, if it works ok after the change, put it here for further ideas: https://codereview.stackexchange.com/
I'm new to Stackoverflow so hopefully I have posted this question in the right place.
I'm having trouble getting my code to work in VBA. I want it to select columns D:F until the last cell value. With this selection, I would like to change the case of the cells (they are currently uppercase) to Proper case.
Dim Lastrow As Integer
Dim range As Variant
With Worksheets("Overdue PO")
Lastrow = .Cells(Rows.Count, "D").End(xlUp).Row
.range("D2:F" & Lastrow).Select
range = Selection.Value
End With
Application.Proper (range)
It currently selects the range until the bottom row, but it doesn't change the case of text. No error appears when running the code.
Thanks in advance :)
Try this:
Dim Lastrow As Integer
With Worksheets("Overdue PO")
Lastrow = .Cells(Rows.Count, "D").End(xlUp).Row
.Range("D2:F" & Lastrow).Value = .Evaluate("INDEX(PROPER(D2:F" & Lastrow & "),)")
End With
It will be near instant, without the need for loops.
Also using .Select or .Activate also slow down the code, aoid them if possible by referring to the cells directly.
Try this
Sub test()
Dim Lastrow As Integer
Dim range As range
Dim c As range
With Worksheets("Overdue PO")
Lastrow = Columns("D:F").Cells.Find(What:="*", LookIn:=xlValues, SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Row
.range("D2:F" & Lastrow).Select
Set range = Selection
End With
For Each c In range
c.Value = Application.WorksheetFunction.Proper(c.Value)
Next c
End Sub
Application.WorksheetFunction.Proper(range) should do it. See https://msdn.microsoft.com/en-us/library/office/ff834434.aspx for documentation on WorksheetFunction
I wanted to use this with a named range, and was kindly provided the following code. Perhaps it will assist someone else:
Sub m_MakeProper()
'2/8/2018
'
Application.Volatile True
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Application.DisplayStatusBar = False
'
Worksheets("test").Activate
'
Dim LastRow As Long
Dim LastCol As Integer
Dim cell As Variant
Dim thiswksht As Worksheet
Dim thiswb As Workbook
'
'
Set thiswksht = ActiveSheet
If thiswksht.AutoFilterMode Then
AutoFilterMode = False
End If
'
With thiswksht
LastRow = Cells(Cells.Rows.Count, "A").End(xlUp).Row
LastCol = Cells(1, Columns.Count).End(xlToLeft).Column
End With
'
Cells(1, 1).Activate
Rows(1).find("Status").Select
Range(ActiveCell.Address, Cells(LastRow, ActiveCell.Column)).Select
Selection.Name = "c_P_Status"
With Range("c_P_Status")
.Value = Application.Evaluate("INDEX(PROPER(" & .Address & "),0)")
End With
'
End Sub
I have been a silent reader on here for a few months but have been struggling with this code for a week now, so thought i would see if anyone can help.
I have a worksheet where sheet 1 contains information for users to input data.
Column A ask a question, column C is where the user will type in an answer.
Row 4 asks how many configurations there will be. depending on what number they input depends on how many cells light up to the right ie if 1 then D4 goes yellow, if 2 then D4 and E4 go yellow (using conditional formatting)
The user will then enter the title into the highlighted cell (D4,E4 ,F4 etc)
I want to create a new sheet at the end of the sheet for each configuration.
then NAME the new sheet by the text entered in D4, E4 etc.
the code I have so far is:
Option Explicit
Sub InsertSupplierSheet()
Dim ws As Worksheet
Dim tmpSht As Worksheet
Dim Lastcol As Integer, i As Integer, j As Integer
Dim DESCRANGE As Range
'~~> Change Sheet1 to the sheet which has all the data
Set ws = ThisWorkbook.Worksheets(1)
With ws
Lastcol = ActiveSheet.Cells(4, Columns.Count).End(xlToLeft).Column
If Lastcol < 4 Then Exit Sub
For i = 3 To Lastcol
If DoesSheetExist(ActiveSheet.Cells(4 & i).Value) Then
Set tmpSht = ActiveSheet.Cells(4 & i).Value
Else
Sheets.Add After:=Sheets(Sheets.Count)
Set tmpSht = ActiveSheet
tmpSht.Name = "NEWSHEET"
End If
.Rows("1:3").Copy tmpSht.Rows(1)
For j = 1 To 4
tmpSht.Columns(j).ColumnWidth = .Columns(j).ColumnWidth
Next j
.Rows(i).Copy tmpSht.Rows(4)
Next
End With
End Sub
Function DoesSheetExist(Sht As String) As Boolean
Dim ws As Worksheet
On Error Resume Next
Set ws = Sheets(ws)
On Error GoTo 0
If Not ws Is Nothing Then DoesSheetExist = True
End Function
I put in "NEWSHEET" to see if even creates a new sheet, but it still fails. I just cant see where I am going wrong.
Any help /advise is welcomed.
EDIT .
I cant work out why though.
The last col will be H4 so lastcol would be "8" .
Then for i = 4 to 8 run the loop. there are descriptions in each of the cells in row 4 so i don't see why it would work for 2 instantness and then fail ?
I dont know if this would make it easier but I have the number of sheets i want to create in cell C4 so i could use this rather than looking up populated cells. so if C4 is 2 then I want to add 2 sheets named as the content of D4, E4. if C4 is 3 then I want to add 3 sheets names as content of D3,E3,F3. Am I making this harder than I need too ?
UPDATE
I figured out the copying over of info is affecting this loop. and amended the code to this.
Sub InsertSupplierSheet()
Dim ws As Worksheet
Dim tmpSht As Worksheet
Dim Lastcol As Integer, i As Integer, j As Integer
Dim DESCRANGE As Range
Dim sShtName As String 'Dimension sheet name variable
'~~> Change Sheet1 to the sheet which has all the data
Set ws = ThisWorkbook.Worksheets(1)
With ws
Lastcol = ActiveSheet.Cells(4, Columns.Count).End(xlToLeft).Column
If Lastcol < 4 Then Exit Sub
For i = 4 To Lastcol
sShtName = ActiveSheet.Cells(4, i).Value2 'Set sShtName to cell value within loop
If DoesSheetExist(sShtName) Then 'Use sShtName to call "Exists" function
Set tmpSht = Sheets(sShtName)
Else
Sheets.Add After:=Sheets(Sheets.Count)
Set tmpSht = ActiveSheet
tmpSht.Name = sShtName 'Change name to sShtName
End If
.Rows("1:3").Copy tmpSht.Rows(1)
.Rows(13).Copy tmpSht.Rows(4)
Next
End With
End Sub
Function DoesSheetExist(Sht As String) As Boolean
Dim ws As Worksheet
On Error Resume Next
Set ws = Sheets(Sht)
On Error GoTo 0
If Not ws Is Nothing Then DoesSheetExist = True
End Function
this is doing what i want it to do with a couple of small exceptions.
the Sheets are being named by the cells in D1 , then E13,F13,G13,H13 So i need to figure out where that info is coming from.
the final bit is that due to my conditional formatting in the First sheet, I am getting text on black backgrounds in the copy cells, but that is the very least of my worries !
UPDATE
Found the error -
sShtName = ActiveSheet.Cells(4, i).Value2
should be
sShtName = Worksheets(1).Cells(4, i).Value2
You are calling your cells incorrectly. Use (4, i) instead of (4 & i).
The way you were calling it concatenated it to 43, which resulted in you checking cell AQ1 (AQ being the 43rd column) for the sheet reference.
Edit: I just walked through it a bit and found a couple of other errors. You need to set the sheet name to sht in your 'exists' function, and I'm assuming you want to set tmpSht to a sheet, so you need to encase it in sheets(). Try this:
Sub InsertSupplierSheet()
Dim ws As Worksheet
Dim tmpSht As Worksheet
Dim Lastcol As Integer, i As Integer, j As Integer
Dim DESCRANGE As Range
Dim sShtName As String 'Dimension sheet name variable
'~~> Change Sheet1 to the sheet which has all the data
Set ws = ThisWorkbook.Worksheets(1)
With ws
Lastcol = ActiveSheet.Cells(4, Columns.Count).End(xlToLeft).Column
If Lastcol < 4 Then Exit Sub
For i = 4 To Lastcol
sShtName = ActiveSheet.Cells(4, i).Value2 'Set sShtName to cell value within loop
If DoesSheetExist(sShtName) Then 'Use sShtName to call "Exists" function
Set tmpSht = Sheets(sShtName)
Else
Sheets.Add After:=Sheets(Sheets.Count)
Set tmpSht = ActiveSheet
tmpSht.Name = sShtName 'Change name to sShtName
End If
.Rows("1:3").Copy tmpSht.Rows(1)
For j = 1 To 4
tmpSht.Columns(j).ColumnWidth = .Columns(j).ColumnWidth
Next j
.Rows(i).Copy tmpSht.Rows(4)
Next
End With
End Sub
Function DoesSheetExist(Sht As String) As Boolean
Dim ws As Worksheet
On Error Resume Next
Set ws = Sheets(Sht)
On Error GoTo 0
If Not ws Is Nothing Then DoesSheetExist = True
End Function
Instead of adding the new sheet and then setting the activesheet to the tmpsht you could use a shorter way (see below). And why did you set the ws if you don't use it....
Sub InsertSupplierSheet()
Dim ws As Worksheet
Dim tmpSht As Worksheet
Dim Lastcol As Integer, i As Integer, j As Integer
Dim DESCRANGE As Range
Set ws = ThisWorkbook.Worksheets(1)
With ws
Lastcol = .Cells(4, .Columns.Count).End(xlToLeft).Column
If (Lastcol < 4) Then
Exit Sub
End If
For i = 4 To Lastcol
If (DoesSheetExist(.Cells(4, i).Value2) = True) Then
Set tmpSht = Sheets(.Cells(4, i).Value)
Else
Set tmpSht = Sheets.Add After:=Sheets(Sheets.Count)
tmpSht.Name = "NEWSHEET"
End If
.Rows("1:3").Copy tmpSht.Rows(1)
For j = 1 To 4
tmpSht.Columns(j).ColumnWidth = .Columns(j).ColumnWidth
Next j
.Rows(i).Copy tmpSht.Rows(4)
Next i
End With
End Sub
Function DoesSheetExist(Sht As String) As Boolean
Dim ws As Worksheet
On Error Resume Next
Set ws = Sheets(Sht)
On Error GoTo 0
If Not ws Is Nothing Then
DoesSheetExist = True
Else
DoesSheetExist = False
End If
End Function
This was my final code. There were a few tweaks, Firstly I added a formula in row 6 to shorten the name of row 4 to a 10 character name as I found the tab names were too long (hence the code for the naming refers to row 6. I also added some custom text to add into each sheet and some formatting
Option Explicit
Sub InsertSupplierSheet()
Dim ws As Worksheet
Dim tmpSht As Worksheet
Dim Lastcol As Integer
Dim i As Integer
Dim j As Integer
Dim DESCRANGE As Range
Dim sShtName As String 'Dimension sheet name variable
'~~> Change Sheet1 to the sheet which has all the data
Set ws = ThisWorkbook.Worksheets(1)
With ws
Lastcol = ActiveSheet.Cells(4, Columns.Count).End(xlToLeft).Column ' work with the template sheet
If Lastcol = 3 Then Exit Sub 'repeat these steps from the first config to the last
For i = 4 To Lastcol
sShtName = Worksheets(1).Cells(6, i).Value2 'Set sShtName to cell value within loop
If DoesSheetExist(sShtName) Then 'Use sShtName to call "Exists" function
Set tmpSht = Sheets(sShtName)
Else
Sheets.Add After:=Sheets(Sheets.Count)
Set tmpSht = ActiveSheet
tmpSht.Name = sShtName 'Change name to sShtName tmpSht.Name = sShtName
End If
.Rows("1:3").Copy tmpSht.Rows(1) ' Format the cell width in the new sheet
.Rows(13).Copy tmpSht.Rows(4)
tmpSht.Range("A1").Value = Worksheets(1).Cells(4, i).Value2
Range("A1").ColumnWidth = 30
Range("B1").ColumnWidth = 0
Range("C1").ColumnWidth = 30
Range("D1:K1").ColumnWidth = 10
Range("D4:J4").Font.Color = vbWhite ' format the colour of the text in the new sheet
Range("C1") = " " ' Negate info in cell C1
With Range("A1:M5") ' add borders
'Clear existing
.Borders.LineStyle = xlNone
'Apply new borders
.BorderAround xlContinuous
.Borders(xlInsideHorizontal).LineStyle = xlContinuous
.Borders(xlInsideVertical).LineStyle = xlContinuous
End With
With Range("A1:C4") ' set colours for the new sheet
.Font.Color = vbBlack
.Interior.Color = vbWhite
End With
Range("D4:J4").Font.Color = vbWhite ' set colour of the numbers to white to show on black background
Range("A5") = "Unit cost in " & Worksheets(1).Cells(17, 3).Value2
Range("A6") = "CUSTOM TEXT ONE."
Range("A7") = "NOTE if quantity " & Range("D4").Value2 + 5 & " is ordered then total cost will be your unit cost for " & Range("D4").Value2 & " multiplied by " & Range("D4").Value2 + 5 & " .This applies up to the quantity of " & Range("E4").Value2 - 1
Range("A8") = "CUSTOM TEXT 2"
Next i
End With
End Sub
Function DoesSheetExist(Sht As String) As Boolean
Dim ws As Worksheet
On Error Resume Next
Set ws = Sheets(Sht)
On Error GoTo 0
If Not ws Is Nothing Then DoesSheetExist = True
End Function