Excel to PDF, multiple ranges same sheet (string) but PrintArea 255 string limit - excel

I believe ranges have a 255 character limit, so I've split the ranges up in 6 cells
B1 through B6 (cell B1 and cell B2 examples below both well below 255 characters).
A1:I15, A17:I40, A42:I65, A92:I114, A116:I140, A142:I168, A170:I196, A198:I224, A226:I252, A254:I280, A282:I308, A310:I336, A338:I364, A366:I392, A394:I420, A422:I448
A450:I476, A478:I504, A526:I552, A554:I580, A582:I608, A610:I636, A638:I664, A666:I690, A692:I707, A730:I750, A752:I773, A775:I794, A796:I815, A817:I830, A855:I877, A879:I905, A907:I926
I tried the Union function to generate a PDF from these ranges but somehow I am only getting the ranges from B1! B2 gets ignored. Here's my code:
Set rng = Union(shTemp.Range("B1"), shTemp.Range("B2"))
shTransformed.Activate
With ActiveSheet.PageSetup
.Zoom = False
.Orientation = xlPortrait
.FitToPagesWide = 1
.FitToPagesTall = False
.PrintArea = rng
End With
ActiveSheet.ExportAsFixedFormat _
Type:=xlTypePDF, _
Filename:="c:\temp\test.pdf", _
Quality:=xlQualityStandard, _
IgnorePrintAreas:=False, _
IncludeDocProperties:=True, _
OpenAfterPublish:=True

May use this workaround to bypass 255 character limit of print area range address by adding Horizontal page breaks and hiding the rows in between print areas. However it is applicable in this case only as the right most column in each print areas are same (i.e. I) and also this method requires each print areas is to be separated by at least a row.
It is tested successfully with the range string as defined in OP. Make some modification regarding Sheets name, range etc.
Sub test()
Dim shTemp As Worksheet, shTr As Worksheet
Dim HideRng As Range, Rng As Range, MainRng As Range
Dim Ar As Range, cel As Range
Set shTemp = ThisWorkbook.Sheets(1)
Set shTr = ThisWorkbook.Sheets(2)
'To Dynamically Select Range containing Addresses
Dim SelRng As Range
Set SelRng = shTemp.Range("B1:B6") ' Default range
shTemp.Activate
On Error Resume Next
Set SelRng = Application.InputBox("Select the range containing Print Range Addresses", "Select Range", SelRng.Address, , , , , 8)
If Err > 0 Then
Err.Clear
Exit Sub
End If
On Error GoTo 0
If SelRng Is Nothing Then Exit Sub
For Each cel In SelRng.Cells
If cel.Value <> "" Then
If Not Range(cel.Value) Is Nothing Then
'Debug.Print Range(cel.Value).Address
If Rng Is Nothing Then
Set Rng = Range(cel.Value)
Else
Set Rng = Union(Rng, Range(cel.Value))
End If
End If
End If
Next
If Rng Is Nothing Then Exit Sub
With shTr
.Cells.PageBreak = xlPageBreakNone
pg = 1
maxcol = 1
For Each Ar In Rng.Areas
'Vartical Pagebreak: it is applicable only in this case where right column is same
If pg = 1 Then
Set MainRng = Ar(1, 1)
.VPageBreaks.Add Ar(1, Ar.Columns.Count).Offset(0, 1)
End If
'Ar(1, 1).Value = "Page " & pg
.HPageBreaks.Add Ar(Ar.Rows.Count, Ar.Columns.Count).Offset(1, 0)
If pg > 1 Then
If HideRng(HideRng.Rows.Count, 1).Row < Ar(1, 1).Row Then
Set HideRng = Range(HideRng, Ar(1, 1).Offset(-1, 0))
HideRng.EntireRow.Hidden = True
End If
End If
Set HideRng = Ar(Ar.Rows.Count, 1).Offset(1, 0)
If pg = Rng.Areas.Count Then Set MainRng = Range(MainRng, Ar(Ar.Rows.Count, Ar.Columns.Count))
pg = pg + 1
Next
End With
shTr.Activate
With ActiveSheet.PageSetup
.Zoom = False
.Orientation = xlPortrait
.FitToPagesWide = 1
.FitToPagesTall = False
.PrintArea = MainRng.Address
End With
ActiveSheet.ExportAsFixedFormat _
Type:=xlTypePDF, _
Filename:="c:\users\user\Desktop\test.pdf", _
Quality:=xlQualityStandard, _
IgnorePrintAreas:=False, _
IncludeDocProperties:=True, _
OpenAfterPublish:=True
End Sub
Screen Shot of created PDF

For some reason Ahmed AU's code didn't work 100% for me so I changed it a little. Instead of hiding the rows I don't use I unhide the rows I use.
With shTransformed
.Cells.PageBreak = xlPageBreakNone
.Rows.EntireRow.Hidden = True
.VPageBreaks.Add shTransformed.Range("J1")
For Each Ar In Rng.Areas
.Range(Ar.Address).EntireRow.Hidden = False
.HPageBreaks.Add Ar(Ar.Rows.Count, Ar.Columns.Count).Offset(1, 0)
Next Ar
End With
Set MainRng = shTransformed.Range("A" & shTransformed.Cells(1, 1).End(xlDown).Row - 1 & ":I" & shTransformed.Cells(shTransformed.Rows.Count, 1).End(xlUp).Row)
'Export to PDF code here

.PrintArea needs a string instead of a range. So right now, it only takes the value from the first cell of you range, which is B1. You need to concatenate the values themselves and use the concatenated string as value for .PrintArea.
https://learn.microsoft.com/en-us/office/vba/api/excel.pagesetup.printarea

Related

Count of distinct values from filtered column

I have one Excel sheet with 6000 rows. I need to delete entire rows if distinct values are less than, say, three in one particular column.
Per below example:
In column-A with the list of colours and in column-B with names.
If I filter any 'name in column-B and in column-A, if less than three distinct values = true then entire row should be deleted.
Rows with name- Chary should be deleted.
A B
Color Employee
Red Dev
blue Dev
blue Dev
Red Dev
black Dev
Red Dev
Red Chary
blue Chary
blue Chary
Red Chary
Red Chary
Red Chary
With my code:
First I filter name in column-B then paste the filtered data new workbook and there I will remove duplicates from column-A then will get the unique count.
If the unique count is less than 3 then activate the main sheet and will delete filtered rows and loop to next name.
Sub Del_lessthan_5folois()
Application.ScreenUpdating = False
Application.DisplayAlerts = False
t = Now()
Set wb = ActiveWorkbook
Sheets("VALID ARNS").Activate
iCol = 2 '### criteria column
Set ws = Sheets("VALID ARNS")
Sheets("VALID ARNS").Activate
Set rnglast = Columns(iCol).Find("*", Cells(1, iCol), , , xlByColumns, xlPrevious)
ws.Columns(iCol).AdvancedFilter Action:=xlFilterInPlace, Unique:=True
Set rngUnique = Range(Cells(2, iCol), rnglast).SpecialCells(xlCellTypeVisible)
Workbooks.Add
Set newb = ActiveWorkbook
For Each strItem In rngUnique
If strItem <> "" Then
ws.UsedRange.AutoFilter Field:=iCol, Criteria1:=strItem.Value
newb.Activate
ws.UsedRange.SpecialCells(xlCellTypeVisible).Copy Destination:=[A1]
Application.CutCopyMode = False
Cells.EntireColumn.AutoFit
Dim uniq As Range
Set uniq = Range("A1:S" & Range("A" & Rows.Count).End(xlUp).Row)
uniq.RemoveDuplicates Columns:=7, Header:=xlYes
LastRow = ActiveSheet.UsedRange.Rows.Count
Cells.Delete Shift:=xlUp
Range("A1").Select
wb.Activate
If LastRow < "3" Then
ActiveSheet.AutoFilter.Range.Offset(1,0).Rows.SpecialCells(xlCellTypeVisible).Delete (xlShiftUp)
End If
End If
Next
ws.ShowAllData
MsgBox "The entire process took! " & Format(Now() - t, "hh:mm:ss") & " Minutes"
ActiveSheet.AutoFilterMode = False
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub
My code works in step by step debug mode but when run it skips a lot of rows.
Can this be related to more than 6000 rows?
How do I get the count of distinct values in Column-A when filtered in Column-B?
It's not exactly the same code that you posted as I had some troubles with it, but here's an alternative solution. I simply copy the data into another sheet (please add sheet called "Results" before you run my code), add two more columns with formulas (these will check if a given "Employee" should be deleted), filter on "TRUE" and then delete relevant rows.
From what I tested such solution seems to be faster than applying Advanced Filters, checking for unique values and then looping through the whole dataset. I hope it will work fine for your setup.
Here's the code:
Sub DeleteRows()
Dim t As Variant
Dim iCol As Long, lngLastRow As Long
Dim wsOrig As Worksheet, wsNew As Worksheet
With Application
.ScreenUpdating = False
.DisplayAlerts = False
End With
t = Now()
Set wsOrig = Sheets("VALID ARNS")
Set wsNew = Sheets("Results")
iCol = 2 '### criteria column
With wsOrig
lngLastRow = .Columns(iCol).Find("*", Cells(1, iCol), , , xlByColumns, xlPrevious).Row
'copy into Results sheet
.Range("A1:B" & lngLastRow).Copy wsNew.Range("A1")
With wsNew
'add formulas
.Range("C1:D1").Value = VBA.Array("Instance", "Delete?")
.Range("C2:C" & lngLastRow).Formula = "=COUNTIFS($A$2:A2,A2,$B$2:B2,B2)"
.Range("D2:D" & lngLastRow).Formula = "=SUMIFS($C$2:$C$" & lngLastRow & ",$B$2:$B$" & lngLastRow & ",B2,$C$2:$C$" & lngLastRow & ",1)<3"
'delete when column D = TRUE
.Range("A1:D" & lngLastRow).AutoFilter Field:=4, Criteria1:="TRUE"
.Range("D2:D" & lngLastRow).SpecialCells(xlCellTypeVisible).Rows.Delete
'clear
.Range("A1:B" & lngLastRow).AutoFilter
.Range("C:D").Clear
End With
End With
MsgBox "The entire process took! " & Format(Now() - t, "hh:mm:ss") & " Minutes"
With Application
.ScreenUpdating = True
.DisplayAlerts = True
End With
End Sub
"VALID ARNS" sheet:
"Results" sheet (after running the code):
Edit:
Another option, using Scripting.Dictionary functionality:
Public Function getUnique(ByVal rngVals As Excel.Range) As Variant()
Dim objDictionary As Object
Dim rngRow As Excel.Range
Dim rngCell As Excel.Range
Dim strKey As String
Set objDictionary = CreateObject("Scripting.Dictionary")
For Each rngRow In rngVals.Rows
For Each rngCell In rngRow.Cells
strKey = strKey & "||" & rngCell.Text
Next rngCell
With objDictionary
If Not .Exists(Key:=Mid$(strKey, 3)) Then
Call .Add(Key:=Mid$(strKey, 3), Item:=Mid$(strKey, 3))
End If
End With
strKey = ""
Next rngRow
getUnique = objDictionary.Keys
Set rngVals = Nothing
Set rngRow = Nothing
Set rngCell = Nothing
End Function
Public Sub CountUnique()
Dim rngVals As Excel.Range
Dim varUnique() As Variant
Dim rngCell As Excel.Range
Dim varTemp As Variant
Set rngVals = Sheet3.Range("A2:B13").SpecialCells(12)
varUnique = getUnique(rngVals)
For Each rngCell In rngVals.Columns(2).Cells
varTemp = Filter(varUnique, rngCell.Text, True)
Debug.Print rngCell.Text, UBound(varTemp) - LBound(varTemp) + 1
Erase varTemp
Next rngCell
Set rngVals = Nothing
Set rngCell = Nothing
Erase varUnique
End Sub

Selection based on finding 2 different words in 2 columns

I would like to do the following using Excel VBA:
1) look for a certain word_1 within a column;
2) if word_1 was found in step (1), go one column to the right and look for another word which is called word_2. If word_2 was found as well, delete the entire row.
If on the other hand, word_2 was not found, the row does not have to be deleted.
The general idea is to search for multiple words in one column and if they are found, also double-check (for safety) if certain affiliated words are in column 2. Only then the entire rows should be deleted.
I made the following little example for testing:
Col1 Col2
xxx xxx
xxx xxx
xxx xxx
findme acg
xxx xxx
findme xxx
In this example I am searching for the word "findme" in column 1 and for the associated word "acg" in column 2. As you can see, row 4 would have to be deleted because both words occur in one row, as opposed to e.g. row 6, where this is not the case.
My final code:
Sub xxx()
Dim aCell As Range, bCell As Range, aSave As String
Dim fndOne As String, fndTwo As String
fndOne = "findme"
fndTwo = "acg"
Dim ws As Worksheet: Set ws = ActiveWorkbook.ActiveSheet
Application.DisplayAlerts = False
Application.ScreenUpdating = False
With ws
Set aCell = .Columns(1).Find(What:=fndOne, LookIn:=xlValues, _
lookat:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not aCell Is Nothing Then
aSave = aCell.Address
Do
If LCase(.Cells(aCell.row, 2).Value) Like Chr(42) & fndTwo & Chr(42) Then
If bCell Is Nothing Then
Set bCell = .Range("A" & aCell.row)
Else
Set bCell = Union(bCell, .Range("A" & aCell.row))
End If
End If
Set aCell = .Columns(1).FindNext(After:=aCell)
Loop Until aCell.Address = aSave
End If
Set aCell = Nothing
If Not bCell Is Nothing Then bCell.EntireRow.Delete
End With
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
If you used the Range.Find method and Range.FindNext method, deleting as you go and checking for matching records after each deletion, you should be able to loop through the possibilities quickly.
'delete rows as they are found
Sub delTwofers()
Dim rw As Long, n As Long, cnt As Long, rng As Range
Dim v As Long, sALLTERMs As String, vPAIRs As Variant, vTERMs As Variant
On Error GoTo bm_SafeExit
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
Debug.Print Timer
sALLTERMs = "aa;bb|cc;dd|ee;ff"
With Worksheets("Sheet1") 'set this worksheet reference properly!
vPAIRs = Split(LCase(sALLTERMs), Chr(124))
For v = LBound(vPAIRs) To UBound(vPAIRs)
vTERMs = Split(vPAIRs(v), Chr(59))
cnt = Application.CountIfs(.Columns(1), Chr(42) & vTERMs(0) & Chr(42), .Columns(2), Chr(42) & vTERMs(1) & Chr(42))
rw = 1
For n = 1 To cnt
rw = .Columns(1).Find(what:=vTERMs(0), lookat:=xlPart, _
after:=.Columns(1).Cells(rw + (rw <> 1)), MatchCase:=False).Row
Do While True
If LCase(.Cells(rw, 2).Value2) Like Chr(42) & vTERMs(1) & Chr(42) Then
.Rows(rw).Delete
Exit Do
Else
rw = .Columns(1).FindNext(after:=.Cells(rw, 1)).Row
End If
Loop
Next n
Next v
End With
Debug.Print Timer
bm_SafeExit:
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
'collect rows with Union, delete them all at once
Sub delTwofers2()
Dim rw As Long, n As Long, cnt As Long, rng As Range
Dim v As Long, sALLTERMs As String, vPAIRs As Variant, vTERMs As Variant
On Error GoTo bm_SafeExit
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
Debug.Print Timer
sALLTERMs = "aa;bb|cc;dd|ee;ff"
With Worksheets("Sheet1") 'set this worksheet reference properly!
vPAIRs = Split(LCase(sALLTERMs), Chr(124))
For v = LBound(vPAIRs) To UBound(vPAIRs)
vTERMs = Split(vPAIRs(v), Chr(59))
cnt = Application.CountIfs(.Columns(1), Chr(42) & vTERMs(0) & Chr(42), .Columns(2), Chr(42) & vTERMs(1) & Chr(42))
rw = 1
For n = 1 To cnt
rw = .Columns(1).Find(what:=vTERMs(0), lookat:=xlPart, _
after:=.Columns(1).Cells(rw), MatchCase:=False).Row
Do While True
If LCase(.Cells(rw, 2).Value2) Like Chr(42) & vTERMs(1) & Chr(42) Then
If rng Is Nothing Then
Set rng = .Cells(rw, 1)
Else
Set rng = Union(rng, .Cells(rw, 1))
End If
Exit Do
Else
rw = .Columns(1).FindNext(after:=.Cells(rw, 1)).Row
End If
Loop
Next n
Next v
End With
Debug.Print Timer 'check timer before deleting discontiguous rows
If Not rng Is Nothing Then _
rng.EntireRow.Delete
Debug.Print Timer
bm_SafeExit:
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
By first checking to make sure there is something to delete, some error control can be avoided; you only need to find the entry for the double matching criteria that you know exists.
Addendum: Deleting a collection of discontiguous rows is time consuming. The second routine (delTwofers2) above was 5% slower that the one that deleted rows as they were found. 25,000 values, 755 random deletions - 3.60 seconds for the first; 3.75 seconds for the latter.
This code applies a filter to the first two columns of the used range using your criteria. It then deletes the visible rows:
Sub DeleteSelected()
Dim RangeToFilter As Excel.Range
Set RangeToFilter = ActiveSheet.UsedRange
With RangeToFilter
.AutoFilter Field:=1, Criteria1:="find me"
.AutoFilter Field:=2, Criteria1:="access granted"
.SpecialCells(xlCellTypeVisible).EntireRow.Delete Shift:=xlUp
End With
End Sub

Deducing column from User defined range in Excel VBA

Edit: #TimWilliams I edited the code as follows but it it doesn't run at all now. ANy thoughts?
Sub Item_Fix()
Dim rng As Range, col As Range, arr
Dim sht As Worksheet, c As Range, tmp
On Error Resume Next 'in case user cancels
Set rng = Application.InputBox( _
Prompt:="Please select the Items to update. " & _
" (e.g. Column A or Column B)", _
Title:="Select Range", Type:=8)
On Error GoTo 0
' Set hdr = Application.InputBox( _
' Prompt:="Does your selection contain headers?", _
' Title:="Header Option")
hdr = MsgBox("Does your selection contain a header?", vbYesNo + vbQuestion, "Header Option")
If rng Is Nothing Then Exit Sub
If rng.Columns.Count > 1 Then
MsgBox "Please select only a single column!", vbExclamation
Exit Sub
End If
Set sht = rng.Parent
Set col = sht.Range(sht.Cells(2, rng.Column), _
sht.Cells(sht.Rows.Count, rng.Column).End(xlUp))
Application.ScreenUpdating = False
If hdr = vbYes Then
For Each c In col.Cells
tmp = Trim(c.Value)
If Len(tmp) > 0 And Len(tmp) < 9 And Row > 1 Then
c.NumberFormat = "#"
c.Value = Right("000000000" & tmp, 9)
End If
Next c
End If
If hdr = vbNo Then
For Each c In col.Cells
tmp = Trim(c.Value)
If Len(tmp) > 0 And Len(tmp) < 9 Then
c.NumberFormat = "#"
c.Value = Right("000000000" & tmp, 9)
End If
Next c
Application.ScreenUpdating = True
End If
End Sub
I'm trying to write a function that will insert leading zeroes into a column that a user specifies. Honestly, I would love for this to be like the Excel Menu Data > Remove Duplicates option. I want to click on a menu button and then select my range and let it do the magic, unfortunately I keep getting errors when trying to deduce the column that has been selected. Other than that issue, it should work fine. My code is below. Any help would be greatly appreciated!
Sub Item_Fix()
'Set Item = Application.InputBox("Select the range that contains the Items").Column
Set IC = Application.InputBox(Prompt:= _
"Please select the Range of Items. (e.g. Column A or Column B)", _
Title:="SPECIFY RANGE", Type:=8).Column
'Set Items = vRange.Column
Set Items = IC.Column
Lastrow = Worksheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row
Items.EntireColumn.Offset(0, 1).Insert
For i = 2 To Lastrow
Cells(i, Items + 1).Formula = "=Text(" & Cells(i, Items) & ",""000000000"")"
Next i
NewColumn = Items + 1
NewColumn.EntireColumn.Copy
Items.PasteSpecial xlPasteValues
NewColumn.EntireColumn.Delete
End Sub
#Jeeped has the right approach I think, but since you asked for a version of your original...
Sub Item_Fix()
Dim rng As Range, col As Range, arr
Dim sht As Worksheet, c As Range, tmp
On Error Resume Next 'in case user cancels
Set rng = Application.InputBox( _
Prompt:="Please select the Items to update. " & _
" (e.g. Column A or Column B)", _
Title:="Select Range", Type:=8)
On Error GoTo 0
If rng Is Nothing Then Exit Sub
If rng.Columns.Count > 1 Then
MsgBox "Please select only a single column!", vbExclamation
Exit Sub
End If
Set sht = rng.Parent
Set col = sht.Range(sht.Cells(2, rng.Column), _
sht.Cells(sht.Rows.Count, rng.Column).End(xlUp))
Application.ScreenUpdating = False
For Each c In col.Cells
tmp = Trim(c.Value)
If Len(tmp) > 0 And Len(tmp) < 9 Then
c.NumberFormat = "#"
c.Value = Right("000000000" & tmp, 9)
End If
Next c
Application.ScreenUpdating = True
End Sub
Let the user select a group of cells to receive the procedure. An InputBox method seems like one extra step and an impediment to the workflow.
Sub make_DUNS_number()
Dim duns As Range, tmp As String
For Each duns In Selection
'possible error control on non-numeric values
'if isnumeric(duns.value2) then
tmp = Right("000000000" & Format(duns.Value2, "000000000;#"), 9)
duns.NumberFormat = "#"
duns.Value2 = tmp
'end if
Next duns
End Sub
With that in place, you should have no trouble adding it to the QAT. See Add Buttons to the Quick Access Toolbar and Customize Button Images for more information.
Selection = Evaluate("index(text(" & Selection.Address & ",""'000000000""),,1)")

Hiding Rows if Cell in a Column Contains Certain Text or Autofiltering a Single Field with 4 Criteria

I have a sheet with columns A through M, containing a table including all rows and columns. If, in column E, a cell contains the string(s) "Drive", "Inactivity", or "Halt" then I want the row to be hidden. If, in column E, a cell does not contain the string "UF_", then I want it to be hidden.
I have tried several things and have looked in many places. Here is some code that I have tried:
Try 1 (takes wayyyy to long):
With ActiveSheet
loopct = 2
While loopct < count1
DoEvents
Application.StatusBar = "Making Table " & loopct
txtrmv1 = "Drive"
txtrmv2 = "Inactivity"
txtrmv3 = "Halt"
txtkp = "UF_"
celltxt = .Range("E" & loopct).Value
If InStr(1, celltxt, txtrmv1, vbTextCompare) Then
.Range("E" & loopct).EntireRow.Hidden = True
End If
If InStr(1, celltxt, txtrmv2, vbTextCompare) Then
.Range("E" & loopct).EntireRow.Hidden = True
End If
If InStr(1, celltxt, txtrmv3, vbTextCompare) Then
.Range("E" & loopct).EntireRow.Hidden = True
End If
If InStr(1, celltxt, txtkp, vbTextCompare) Then
.Range("E" & loopct).EntireRow.Hidden = False
Else
.Range("E" & loopct).EntireRow.Hidden = True
End If
loopct = loopct + 1
Wend
End With
Try 2 (runs but accomplishes nothing):
Private Sub HideDrive(ByVal count1 As Long)
Dim ws As Worksheet
Dim rng As Range, aCell As Range, bCell As Range
Set ws = ActiveWorkbook.Sheets("Sheet1")
With ws
Set rng = .Range("E2:E" & CStr(count1))
Set aCell = rng.Find(What:="Drive", LookIn:=xlValues, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=True, SearchFormat:=False)
If Not aCell Is Nothing Then
Set bCell = aCell
Do
aCell.EntireRow.Hidden = True
Set aCell = rng.FindNext(After:=aCell)
Loop While aCell Is Nothing And aCell.Address <> bCell
End If
End With
End Sub
Here is what I was using when I only had one criteria to check for (obviously my sitation has changed):
ActiveWorkbook.ActiveSheet.ListObjects(tblnm).Range.AutoFilter Field:=5, Criteria1:= "=*UF_*"
What can I do to accomplish what I want? I haven't been able to get autofilter to work with more than two criteria. Please let me know!
I couldn't debug and run the other answer given, so I continued working and solved it myself.
Instead of trying to hide each word I didn't want all together, I hid them individually and then called a hidden row deleting function each time.
ActiveSheet.ListObjects.Add(xlSrcRange, Range(DataArea1), , xlYes).Name = _
tblnm
'insert if statement here to change filters based upon area
ActiveWorkbook.ActiveSheet.ListObjects(tblnm).Range.AutoFilter Field:=5, Criteria1:="=*UF_*"
Call RhidRow2(count4)
ActiveSheet.ListObjects(tblnm).Range.AutoFilter Field:=5, Criteria1:="<>*Drive*"
Call RhidRow2(count4)
ActiveSheet.ListObjects(tblnm).Range.AutoFilter Field:=5, Criteria1:="<>*Inactivity*"
Call RhidRow2(count4)
ActiveSheet.ListObjects(tblnm).Range.AutoFilter Field:=5, Criteria1:="<>*Halt*"
Call RhidRow2(count4)
ActiveSheet.ListObjects(tblnm).Range.AutoFilter Field:=8, Criteria1:="<>#VALUE!"
Call RhidRow2(count4)
Here is the hidden row deleter:
Private Sub RhidRow2(ByVal count4 As Long)
Dim count1 As Long 'counters to be used
Dim ws As Worksheet
Dim rngVis As Range
Dim rngDel As Range
Set ws = ActiveSheet
On Error Resume Next
Set rngVis = ws.Range("A2:A" & count4).SpecialCells(xlCellTypeVisible)
On Error GoTo 0
If rngVis Is Nothing Then
ws.Range("Z1").Value = 1
Else
For count1 = count4 To 2 Step -1
If ws.Rows(count1).Hidden = True Then
If rngDel Is Nothing Then
Set rngDel = ws.Rows(count1)
Else
Set rngDel = Union(rngDel, ws.Rows(count1))
End If
End If
Next count1
If Not rngDel Is Nothing Then
Application.DisplayAlerts = False
Intersect(rngDel, rngDel.ListObject.DataBodyRange).Delete 'if row is hidden, delete
Application.DisplayAlerts = True
End If
End If
End Sub
This works better and faster than anything else I had tried or was suggested.
You might be hiding many times. This is better:
If InStr(1, celltxt, txtrmv1, vbTextCompare) > 0 Or _
InStr(1, celltxt, txtrmv2, vbTextCompare) > 0 Or _
InStr(1, celltxt, txtrmv3, vbTextCompare) > 0 Or _
InStr(1, celltxt, txtkp, vbTextCompare) = 0 Then
.Range("E" & loopct).EntireRow.Hidden = True
End If
EDIT: This should be a SIGNIFICANT speedup - it hides 10 rows at a time:
(added Next iRow also)
Option Explicit
Dim ws As Worksheet
Sub Sub1()
Dim iRow&, Count1&, txtrmv1, txtrmv2$, txtrmv3$, txtkp$, celltxt$
Set ws = ActiveWorkbook.Sheets("Sheet1")
Count1 = 65000 ' ??
txtrmv1 = "Drive"
txtrmv2 = "Inactivity"
txtrmv3 = "Halt"
txtkp = "UF_"
For iRow = 2 To Count1
DoEvents
Application.StatusBar = "Making Table " & iRow
celltxt = ws.Range("E" & iRow).Value
If InStr(1, celltxt, txtrmv1, vbTextCompare) > 0 Or _
InStr(1, celltxt, txtrmv2, vbTextCompare) > 0 Or _
InStr(1, celltxt, txtrmv3, vbTextCompare) > 0 Or _
InStr(1, celltxt, txtkp, vbTextCompare) = 0 Then
Call hideSub(iRow) '
End If
Next iRow ' thank you, tannmann357
Call hideSub(0) ' flush
End Sub
Sub hideSub(hideRow&) ' hides 10 rows at a time
Static a1&(10), na1&
Dim i1&, zRange As Range
If hideRow = 0 Then ' finish;end;flush
For i1 = 1 To na1
ws.Rows(a1(i1)).Hidden = True
Next i1
na1 = 0
Else ' store row in array a1
na1 = na1 + 1
a1(na1) = hideRow
If na1 = 10 Then ' hide 10 rows
Set zRange = Union( _
Rows(a1(1)), Rows(a1(2)), Rows(a1(3)), Rows(a1(4)), Rows(a1(5)), _
Rows(a1(6)), Rows(a1(7)), Rows(a1(8)), Rows(a1(9)), Rows(a1(10)))
'Debug.Print zRange.Address
' this works but the syntax seems strange -- help me out
ws.Range(zRange.Address).Rows.Hidden = True
na1 = 0
End If
End If
End Sub
EDIT: for my benefit:
replace
' this works but the syntax seems strange -- help me out
ws.Range(zRange.Address).Rows.Hidden = True
with
ws.Range(zRange).Rows.Hidden = True

Setting up if cell is blank don't continue... and show a message

This code works perfectly. I only have one question, I want to make it so that if there is nothing in cell Q23 that it will not put anything into NCMR Data, and say something... the code is below of what I have, and below it is what I think I need to do to a specific section to work, can someone review and make sure I am on the right path?
Option Explicit
Sub NCMR()
Dim i As Integer
With Application
.ScreenUpdating = False
End With
'Internal NCMR
Dim wsInt As Worksheet
Dim wsNDA As Worksheet
'Copy Ranges
Dim c As Variant
'Paste Ranges
Dim P As Range
'Setting Sheet
Set wsInt = Sheets("NCMR Input")
Set wsNDA = Sheets("NCMR Data")
Set P = wsInt.Range("B61:V61")
With wsInt
c = Array(.Range("B11"), .Range("B14"), .Range("B17"), .Range("B20"), .Range("Q23"), .Range("B23") _
, .Range("Q11"), .Range("Q14"), .Range("Q17"), .Range("Q20"), .Range("R26"), .Range("V23") _
, .Range("V25"), .Range("V27"), .Range("B32"), .Range("B40"), .Range("B46"), .Range("B52") _
, .Range("D58"), .Range("L58"), .Range("V58"))
End With
For i = LBound(c) To UBound(c)
P(i + 1).Value = c(i).Value
Next
With wsNDA
Dim LastRow As Long
LastRow = .Range("A" & Rows.Count).End(xlUp).Row + 1
wsInt.Rows("61").Copy
With .Rows(LastRow)
.PasteSpecial Paste:=xlPasteFormats
.PasteSpecial Paste:=xlPasteValues
.Interior.Pattern = xlNone
End With
With .Range("A" & LastRow)
If LastRow = 3 Then
.Value = 1
Else
.Value = Val(wsNDA.Range("A" & LastRow - 1).Value) + 1
End If
.NumberFormat = "0#######"
End With
End With
With Application
.Range("A61:V61").ClearContents
.ScreenUpdating = True
End With
End Sub
What I want to do I think:
With wsInt
Dim f As Range
Set f = .Cell("Q23")
If IsEmpty(f) Then
MsgBox "The data can't entered, you have not entered any data into the Sales Order field."
Else
c = Array(.Range("B11"), .Range("B14"), .Range("B17"), .Range("B20"), .Range("Q23"), .Range("B23") _
, .Range("Q11"), .Range("Q14"), .Range("Q17"), .Range("Q20"), .Range("R26"), .Range("V23") _
, .Range("V25"), .Range("V27"), .Range("B32"), .Range("B40"), .Range("B46"), .Range("B52") _
, .Range("D58"), .Range("L58"), .Range("V58"))
End If
End With
Maybe as simple as:
With wsInt
If Len(.Range("Q23")) = 0 Then
MsgBox "The data can't be entered, you have not entered any data into the Sales Order field."
Exit Sub
End If
End With 'added this line for clarity

Resources