Ignoring Hidden Sheets In Arrays - vba

I am currently producing a workbook that allows the users to print different reports for different departments.
The workbook has multiple copies of the same sheet for different phases of with the user may only need to use 1 or 2 phases out of a potential of 8 phases.
I have added a form that appears once the print has been pressed that allows users to select a report they would like to print which selects the relevant sheet before printing.
This is the code I have be trying to get to work it ignores the hidden sheets but only prints the current sheet and not the sheets visible within the array.
Sub SelectSheets()
Dim myArray() As Variant
Dim i As Integer
Dim j As Integer
j = 0
For i = 1 To Sheets.Count
If Sheets(i).Visible = True And IsInArray(Sheets(i).Name, Array("Sheet1", "Sheet2", "Sheet3")) Then
ReDim Preserve myArray(j)
myArray(j) = Sheets(i).Name
j = j + 1
End If
Next i
Sheets(myArray).Select
End Sub
Function IsInArray(stringToBeFound As String, arr As Variant)
IsInArray = Not IsError(Application.Match(stringToBeFound, arr, 0))
End Function
Thank you in advance for any help.
Matt

Please take a look at this code.
Sub SelectSheets()
Const ExcludedSheets As String = "Sheet1,Sheet2,Sheet3"
Dim SelectedSheets() As String
Dim Ws As Worksheet
Dim i As Integer
With ActiveWorkbook
ReDim SelectedSheets(.Worksheets.Count)
i = -1
For Each Ws In .Worksheets
If InStr(1, ExcludedSheets, Ws.Name, vbTextCompare) = 0 Then
If Ws.Visible = xlSheetVisible Then
i = i + 1
SelectedSheets(i) = Ws.Name
End If
End If
Next Ws
If i > -1 Then
ReDim Preserve SelectedSheets(i)
.Worksheets(SelectedSheets).Select
End If
End With
End Sub
The code below would print the sheets rather than select them.
Sub PrintSelectedSheets()
' 24 Jan 2018
Const ExcludedSheets As String = "Sheet1,Sheet2,Sheet3"
Dim Ws As Worksheet
With ActiveWorkbook
For Each Ws In .Worksheets
If InStr(1, ExcludedSheets, Ws.Name, vbTextCompare) = 0 Then
With Ws
If .Visible = xlSheetVisible Then .PrintOut
End With
End If
Next Ws
End With
End Sub

Related

Copy corresponding row VBA

I'm using a VBA to copy all the unique values from one sheet to another sheet. My VBA looks like this:
Sub UniqueListSample()
Application.ScreenUpdating = False
Dim lastrow As Long
Dim i As Long
Dim dictionary As Object
Set dictionary = CreateObject("scripting.dictionary")
Set shee = ThisWorkbook.Sheets("Sheet1")
lastrow = shee.Cells(Rows.Count, "B").End(xlUp).Row
On Error Resume Next
For i = 1 To lastrow
If Len(Sheet1.Cells(i, "B")) <> 0 Then
dictionary.Add shee.Cells(i, "B").Value, 1
End If
Next
Sheet3.Range("A3").Resize(dictionary.Count).Value = _
Application.Transpose(dictionary.keys)
Application.ScreenUpdating = True
End Sub
This takes all the unique values from Sheet 1 column B and moves them to sheet 3 column A. What I'm now trying to add is a function that takes the same rows from column C in sheet 1 and paste them into sheet 3 column B.
Is there an easy way to add this to the existing VBA?
please check this:
Option Explicit
Sub UniqueListSample()
Application.ScreenUpdating = False
Dim lastrow As Long
Dim i As Long
Dim dictionary As Object
Dim shee As Worksheet
Set dictionary = CreateObject("scripting.dictionary")
Set shee = ThisWorkbook.Sheets("Sheet1")
lastrow = shee.Cells(Rows.Count, "B").End(xlUp).Row
On Error Resume Next
For i = 1 To lastrow
If Len(Sheet1.Cells(i, "B")) <> 0 Then
dictionary.Add shee.Cells(i, "B").Value, shee.Cells(i, "c").Value
End If
Next
With Sheet3
.Range("A3").Resize(dictionary.Count).Value = _
Application.Transpose(dictionary.keys)
For i = 1 To dictionary.Count
.Cells(i + 2, 2) = dictionary(Sheet3.Cells(i + 2, 1).Value)
Next
End With
Application.ScreenUpdating = True
End Sub
If you just want one column you can utilise the Item. I prefer to avoid the "On Error" statement - the method below will not error if the same key is used (it will just overwrite).
Sub UniqueListSample()
Application.ScreenUpdating = False
Dim lastrow As Long
Dim i As Long
Dim dictionary As Object
Dim shee As Worksheet
Set dictionary = CreateObject("scripting.dictionary")
Set shee = ThisWorkbook.Sheets("Sheet1")
lastrow = shee.Cells(Rows.Count, "B").End(xlUp).Row
With dictionary
For i = 1 To lastrow
If Len(Sheet1.Cells(i, "B")) <> 0 Then
If Not (.Exists(shee.Cells(i, "B").Value)) Then
.Item(shee.Cells(i, "B").Value) = shee.Cells(i, "C").Value
End If
End If
Next
Sheet3.Range("A3").Resize(.Count).Value = Application.Transpose(.keys)
Sheet3.Range("B3").Resize(.Count).Value = Application.Transpose(.items)
End With
Application.ScreenUpdating = True
End Sub

Comparing worksheets in Excel - my range is not matching my array

I want to compare three worksheets (which should be identical) in a workbook and highlight any non-matching cells. I've based the following code on Using VBA to compare two Excel workbooks:
Sub CompareWorksheets()
Dim varSheetA As Worksheet
Dim varSheetB As Worksheet
Dim varSheetC As Worksheet
Dim varSheetAr As Variant
Dim varSheetBr As Variant
Dim varSheetCr As Variant
Dim strRangeToCheck As String
Dim iRow As Long
Dim iCol As Long
Set varSheetA = Worksheets("DS")
Set varSheetB = Worksheets("HT")
Set varSheetC = Worksheets("NM")
strRangeToCheck = ("A1:L30")
' If you know the data will only be in a smaller range, reduce the size of the ranges above.
varSheetAr = varSheetA.Range(strRangeToCheck).Value
varSheetBr = varSheetB.Range(strRangeToCheck).Value
varSheetCr = varSheetC.Range(strRangeToCheck).Value ' or whatever your other sheet is.
For iRow = LBound(varSheetAr, 1) To UBound(varSheetAr, 1)
For iCol = LBound(varSheetAr, 2) To UBound(varSheetAr, 2)
Debug.Print iRow, iCol
If varSheetAr(iRow, iCol) = varSheetBr(iRow, iCol) And varSheetAr(iRow, iCol) = varSheetCr(iRow, iCol) Then
varSheetA.Cells(iRow, iCol).Interior.ColorIndex = xlNone
varSheetB.Cells(iRow, iCol).Interior.ColorIndex = xlNone
varSheetC.Cells(iRow, iCol).Interior.ColorIndex = xlNone
Else
varSheetA.Cells(iRow, iCol).Interior.ColorIndex = 22
varSheetB.Cells(iRow, iCol).Interior.ColorIndex = 22
varSheetC.Cells(iRow, iCol).Interior.ColorIndex = 22
End If
Next
Next
End Sub
The problem is, when "strRangeToCheck" starts at A1, everything works as it should, but as soon as I change the range to something like ("B4:C6"), it looks like the correct comparisons are still being made, but the cells that get highlighted always get shifted back up to cell A1 as the starting point (as opposed to B4, which is what I want). In other words, the highlighting "pattern" is correct, but shifted up and over a few cells.
I expanded on #Vityata example.
CompareWorksheets compares the same range on up to up to 60 Worksheets, whereas CompareRanges will compare ranges of the same size and shape.
Sub Test_Comparisons()
CompareWorksheets "A1:L30", Worksheets("DS"), Worksheets("HT"), Worksheets("NM")
CompareRanges Worksheets("DS").Range("A1:L30"), Worksheets("HT").Range("K11:V40"), Worksheets("NM").Range("A101:L130")
End Sub
Sub CompareWorksheets(CompareAddress As String, ParamArray arrWorkSheets() As Variant)
Application.ScreenUpdating = False
Dim cell As Range
Dim x As Long
Dim bFlag As Boolean
'Reset all the colors
For x = 0 To UBound(arrWorkSheets)
arrWorkSheets(x).Range(CompareAddress).Interior.ColorIndex = xlNone
Next
For Each cell In arrWorkSheets(0).Range(CompareAddress)
bFlag = False
For x = 1 To UBound(arrWorkSheets)
If arrWorkSheets(x).Range(cell.ADDRESS).Value <> cell.Value Then
bFlag = True
Exit For
End If
Next
If bFlag Then
For x = 0 To UBound(arrWorkSheets)
arrWorkSheets(x).Range(cell.ADDRESS).Interior.ColorIndex = 22
Next
End If
Next
Application.ScreenUpdating = True
End Sub
Sub CompareRanges(ParamArray arrRanges() As Variant)
Application.ScreenUpdating = False
Dim cell As Range
Dim x As Long, y As Long, z As Long
Dim bFlag As Boolean
'Reset all the colors
For z = 0 To UBound(arrRanges)
arrRanges(z).Interior.ColorIndex = xlNone
Next
For x = 1 To arrRanges(0).Rows.Count
For y = 1 To arrRanges(0).Rows.Count
For z = 1 To UBound(arrWorkSheets)
If arrWorkSheets(1).Cells(x, y).Value <> arrWorkSheets(z).Cells(x, y).Value Then
bFlag = True
Exit For
End If
Next
If bFlag Then
For z = 0 To UBound(arrWorkSheets)
arrWorkSheets(z).Cells(x, y).Interior.ColorIndex = 22
Next
End If
Next
Next
Application.ScreenUpdating = True
End Sub
What I have understood from the first reading, is that you have 3 worksheets which you want to compare. This code works, if you want to compare a selected range in the first three worksheets in a workbook. It colors the different values in red, in each workbook:
Option Explicit
Sub compareWorksheets()
Dim rngCell As Range
Dim counter As Long
For Each rngCell In Selection
If Worksheets(1).Range(rngCell.Address) <> Worksheets(2).Range(rngCell.Address) _
Or Worksheets(1).Range(rngCell.Address) <> Worksheets(3).Range(rngCell.Address) Then
For counter = 1 To 3
Worksheets(counter).Range(rngCell.Address).Interior.Color = vbRed
Next counter
End If
Next rngCell
End Sub
If you want to compare a range A1:Z10 in the three worksheets, change the words Selection with Worksheets(1).Range("A1:Z10") or simply select the range in a one workbook.

Assign column to an array VBA

I have this code. DataSet is set as a variant.
DataSet = Selection.Value
Works fine but is there a way I can change it to just column A, specifically cells A2 to A502? Ive tried setting that as the range but it doesn't work. It also needs to ignore blank spaces because not all of the cells will have content. I am trying to eliminate the need to highlight the cells as the entries will only be in that specific range.
Try these 2 versions:
Option Explicit
Public Sub getNonemptyCol_ForLoop()
Dim dataSet As Variant, fullCol As Variant, i As Long, j As Long
Dim lrFull As Long, lrData As Long, colRng As Range
Set colRng = ThisWorkbook.Worksheets(1).Range("A2:A502")
fullCol = colRng
lrFull = UBound(fullCol)
lrData = lrFull - colRng.SpecialCells(xlCellTypeBlanks).Count
ReDim dataSet(1 To lrData, 1 To 1)
j = 1
For i = 1 To lrFull
If Len(fullCol(i, 1)) > 0 Then
dataSet(j, 1) = fullCol(i, 1)
j = j + 1
End If
Next
End Sub
Public Sub getNonemptyCol_CopyPaste() 'without using a For loop
Dim dataSet As Variant, ws As Worksheet
Application.ScreenUpdating = False
Set ws = ThisWorkbook.Worksheets(1)
With ws.UsedRange
ws.Activate
.Range("A2:A502").SpecialCells(xlCellTypeConstants).Copy
.Cells(1, (.Columns.Count + 1)).Activate
ActiveSheet.Paste
dataSet = ws.Columns(.Columns.Count + 1).SpecialCells(xlCellTypeConstants)
'dataSet now contains all non-blank values
ws.Columns(.Columns.Count + 1).EntireColumn.Delete
.Cells(1, 1).Activate
End With
Application.ScreenUpdating = True
End Sub
Assign with dynamic column.
Sub SetActiveColunmInArray()
Dim w As Worksheet
Dim vArray As Variant
Dim uCol As Long
Dim address As String
Set w = Plan1 'or Sheets("Plan1") or Sheets("your plan name")
w.Select
uCol = w.UsedRange.Columns.Count
address = w.Range(Cells(1, 1), Cells(1, uCol)).Cells.address
vArray = Range(address).Value2
End Sub

Delete entire Row with zeroes apply to all worksheets

I have VBA code that works to delete entire row when there is an absolute zero value in one a cell column but, I am not able to figure out how to update code to apply to all worksheets (there are 20 Sheets in my workbook):
Can someone help with syntax how to update this code to apply to all worksheets in the workbook.
Sub IfandthenDelete_Button3_Click()
Dim lRow As Long
Dim i As Long
lRow = 3000
Application.ScreenUpdating = False
For i = lRow To 1 Step -1
If Cells(i, 1) = 0 Then
Rows(i).Delete
End If
Next
Application.ScreenUpdating = False
End Sub
You need one more for loop for that.
Sub WorksheetLoop()
Dim wsCount As Integer
Dim j As Integer
Dim lRow As Long
Dim i As Long
lRow = 3000
wsCount = ActiveWorkbook.Worksheets.Count
For j = 1 To wsCount
For i = lRow To 1 Step -1
If ActiveWorkbook.Worksheets(j).Cells(i, 1) = 0 Then
ActiveWorkbook.Worksheets(j).Rows(i).Delete
End If
Next
Next j
End Sub

Loop through each column and delete columns with "0"

I'm not getting any errors but it's not deleting the columns with "0's". I just want to delete columns that have lots of 0's as you can read from my code. I'm not sure what could be wrong so any suggestions are welcome.
Sub Finalize()
Dim finalform As Worksheet
Dim deletename As String
Dim finalworkbook As Workbook
Dim ws As Worksheet
Dim copyrange As Range
Dim columnloop As Range
Application.DisplayAlerts = False
Application.ScreenUpdating = False
Set finalform = Workbooks(ActiveWorkbook.Name).ActiveSheet
For a = 3 To 18
If Range("B" & a).Value <> "" Then
Workbooks.Open finalform.Range("B" & a).Value
Set finalworkbook = Workbooks(ActiveWorkbook.Name)
'Delete sheets
For b = 3 To 12
deletename = finalform.Range("D" & b).Value
If deletename <> "" Then
finalworkbook.Worksheets(deletename).Delete
End If
Next b
'Find, replace, remove
For Each ws In ActiveWorkbook.Worksheets
'Copy paste values
Set copyrange = ws.Cells
copyrange.Copy
copyrange.PasteSpecial xlPasteValues
Application.CutCopyMode = False
'Delete columns with 0
For Each columnloop In copyrange.Columns
d = 0
For c = 1 To 35
If Cells(c, columnloop.Column).Value = "0" Then
d = d + 1
End If
Next c
If d > 5 Then
columnloop.Delete
End If
Next columnloop
Next ws
End If
Next a
Application.DisplayAlerts = True
Application.ScreenUpdating = True
End Sub
Your loop can be replaced with more efficient methods of counting. You should always start at the extents when deleting rows or columns and work toward A1 in order that you do not skip over a column during the next incrementation.
Dim c As Long, ws As Worksheet
'Find, replace, remove
For Each ws In ActiveWorkbook.Worksheets
With ws
.UsedRange.Cells = .UsedRange.Cells.Value
'Delete columns with 0
For c = .UsedRange.Columns.Count To 1 Step -1
If Application.CountIf(.Columns(c), 0) > 5 Then
.Columns(c).EntireColumn.Delete
End If
Next c
End With
Next ws
There are several other areas that could be tweaked. Once this is running to an operational standard, consider posting it on Code Review (Excel) for further improvements.