keep the rows and column hidden while changing row width and column height - excel

I have a code that change the rows height and column width of all the sheets in the workbook from row 1 and column B.
My problem is that its making all my hidden columns and rows also visible.
Please suggest as to how I shud modify the code so that it can change the column width and row height but should be kept them hidden.
Sub rowcolallsheetb()
Dim exworkb As Workbook
Dim xlwksht As Worksheet
Dim lastrow1 As Long
Dim lastcolumn1 As Long
Dim firstrowDB As Long
Dim Z As Integer
Dim ShtNames() As String
ReDim ShtNames(1 To ActiveWorkbook.Sheets.Count)
For Z = 1 To Sheets.Count
ShtNames(Z) = Sheets(Z).Name
Sheets(Z).Select
lastrow1 = Sheets(Z).Cells(Rows.Count, "A").End(xlUp).Row
lastcolumn1 = Sheets(Z).Cells(1, Columns.Count).End(xlToLeft).Column
ActiveWorkbook.Sheets(Z).Range(Sheets(Z).Cells(1, 2), Sheets(Z).Cells(lastrow1, lastcolumn1)).Select
Selection.Cells.RowHeight = 9.4
Selection.Cells.ColumnWidth = 11.2
Next Z
End Sub

Use SpecialCells(xlCellTypeVisible) to exclude the hidden cells from your action:
With ActiveWorkbook.Sheets(Z).Range("B1", Sheets(Z).Cells(lastrow1, lastcolumn1)) _
.SpecialCells(xlCellTypeVisible)
' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.ColumnWidth = 11.2
.RowHeight = 9.4
End With
You could also use
'vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
With Selection.SpecialCells(xlCellTypeVisible)
.ColumnWidth = 11.2
.RowHeight = 9.4
End With
But it's always recommended to avoid using the Select stuff in VBA.

Related

Excel VBA code to copy and paste table rows to PowerPoint until specific row height is met

I already have a working code that copies a table from Excel to PowerPoint and creates more slides and tables (splits the large table into multiple ones) if the sum of the row heights reaches a certain threshold in Excel:
Sub PowerPointTableSplit()
Dim rng As Range
Dim PowerPointApp As Object
Dim myPresentation As Object
Dim mySlide As Object
Dim myShape As Object
Dim lCol As Long
Dim lRow As Long
Dim LastRow As Long
Dim i As Long
Dim j As Integer
Dim rngH As Range
Dim wss As Worksheet
Set wb = Workbooks("Automation Tool.xlsm")
Set ws = wb.Sheets("630")
Set rngH = ws.Range("A1:AB1") 'Header Row (same for all tables)
LastRow = ws.Range("A" & ws.Rows.Count).End(xlUp).Row
With ws.Range("A1:AB" & LastRow)
.Font.Name = "Arial"
.Font.Size = 6
End With
ws.Range("A1:A" & LastRow).EntireRow.AutoFit
i = 2
Set wss = wb.Worksheets.Add
Set PowerPointApp = GetObject(class:="PowerPoint.Application")
Set myPresentation = PowerPointApp.ActivePresentation
'Loop through excel table and cut it after X rows to make it fit on PowerPoint, Copy & Paste table
'wss is a temporary excel sheet to store every X rows (will be deleted at the end)
Do While i <= LastRow
Z = 1 'counter to check row height in excel
RowHeight = 0
Do Until RowHeight > 600
RowHeight = RowHeight + ws.Rows(Z).Height
Z = Z + 1
Loop
j = Application.Min(i + Z, LastRow)
Union(rngH, ws.Range("A" & i, ws.Range("AB" & j))).Copy
wss.Range("A1").PasteSpecial Paste:=xlPasteColumnWidths
wss.Range("A1").PasteSpecial Paste:=xlPasteValues
wss.Range("A1").PasteSpecial Paste:=xlPasteAllUsingSourceTheme
sld.Shapes.PasteSpecial DataType:=ppPasteHTML, Link:=msoFalse
wss.Range("A1:AB" & j - i + 2).Copy
Set sld = myPresentation.Slides.Add(myPresentation.Slides.Count + 1, ppLayoutBlank)
i = j + 1
Loop
'Delte temporary excel sheet wss as not needed anymore
Application.DisplayAlerts = False
wss.Delete
Application.DisplayAlerts = True
Set wss = Nothing
End Sub
After this I am using a code to strech the table in PowerPoint to the whole available space on the slide, this also makes it tricky for me to get the real row height in PowerPoint using the code above as I would have to check the real height after streching the table.
Sub AutoFitTables()
Dim s As Slide
Dim oSh As Shape
Dim oTbl As Table
Dim lRow As Long
Dim lCol As Long
ScreenUpdating = False
For Each s In ActivePresentation.Slides
'ActivePresentation.Slides(Slide.SlideIndex(s)).Select
ActivePresentation.Slides(s.SlideIndex).Select
For Each oSh In s.Shapes
If oSh.HasTable Then
oSh.Left = 0 * 28.3
oSh.Top = 1.5 * 28.3
oSh.Width = 33.867 * 28.35
oSh.ZOrder msoSendToBack
Set oTbl = oSh.Table
For lRow = 1 To oTbl.Rows.Count
For lCol = 1 To oTbl.Columns.Count
With oTbl.Cell(lRow, lCol).Shape
.TextFrame.TextRange.Font.Name = "Arial"
.TextFrame.TextRange.Font.Size = 6
.TextFrame2.VerticalAnchor = msoAnchorMiddle
oTbl.Rows(lRow).Height = 0.5
End With
Next lCol
Next lRow
End If
Next oSh
Next s
ActivePresentation.Slides(1).Select
End Sub
However, since I still want to copy a much wider table, the format in the table shifts as soon as I copy it into PowerPoint, so that the table is too large to be seen completely, the code does not work.
I already have an idea, but the implementation fails. I want to copy the table row after row and after each copy check the total row height in PowerPoint and jump to the next page if the row height of 450 is reached. For this the following code comes into question:
sld.Shapes(X).Table.Rows(Y).Height 'with X and Y looping
I would be thankful for any help and hints.

VBA - How do I randomly select 10% of rows from a column, ensuring they are different and put a Y in column B?

I am looking to randomly select 10% of tasks worked by different users ('originator' Column P) and place a Y in column B to allow checkers to QC the work. If the 10% is not a whole number then I am required to round up i.e. 0.8 would require 1 row and 1.3 would require 2 rows.
I am new to coding I have been able to add code to filter the rows to show the required date and the 'Originator' in column P then name this range as "userNames". I am not sure how to code to select the random 10%. I have changed the part I am struggling with to bold below.
Sub randomSelection()
Dim dt As Date
dt = "20/08/2021"
Dim lRow As Long
'Format date
Range("J:J").Select
Selection.NumberFormat = "dd/mm/yyyy"
'Select User Grogu
ActiveSheet.Range("$A$1:$W$10000").AutoFilter 10, Criteria1:="=" & dt
ActiveSheet.Range("$A$1:$W$10000").AutoFilter Field:=16, Criteria1:= _
"SW\Grogu"
'Name range "userNames"
With ActiveSheet
lRow = .Cells(Rows.Count, 16).End(xlUp).Row
If lRow < 3 Then Exit Sub
.Cells(1, 16).Offset(1, 0).Resize(lRow - 1).SpecialCells(xlCellTypeVisible).Select
End With
Selection.Name = "userNames"
**'Randomly select 10% of rows from originator and put a Y in column B**
'remove all defined names
On Error Resume Next
ActiveWorkbook.Names("userNames").Delete
'Select User Finn
ActiveSheet.Range("$A$1:$W$10000").AutoFilter 10, Criteria1:="=" & dt
ActiveSheet.Range("$A$1:$W$10000").AutoFilter Field:=16, Criteria1:= _
"SW\Finn"
'Name range "userNames"
With ActiveSheet
lRow = .Cells(Rows.Count, 16).End(xlUp).Row
If lRow < 3 Then Exit Sub
.Cells(1, 16).Offset(1, 0).Resize(lRow - 1).SpecialCells(xlCellTypeVisible).Select
End With
Selection.Name = "userNames"
'remove all defined names
On Error Resume Next
ActiveWorkbook.Names("userNames").Delete
'Formate Date back
Range("J:J").Select
Selection.NumberFormat = "yyyy-mm-dd"
End Sub
I had some free time and wrote up an example program that copies 10% of a defined set of rows, and then pastes it into a different sheet. I have added some comments to help explain what each section is achieving.
Sub Example()
'Define the Start and End of the data range
Const STARTROW As Long = 1
Dim LastRow As Long
LastRow = Sheet1.Cells(Sheet1.Rows.Count, 1).End(xlUp).Row
'Create an Array - Length = Number of Rows in the data
Dim RowArr() As Long
ReDim RowArr(STARTROW To LastRow)
'Fill the Array - Each element is a row #
Dim i As Long
For i = LBound(RowArr) To UBound(RowArr)
RowArr(i) = i
Next i
'Shuffle the Row #'s within the Array
Randomize
Dim tmp As Long, RndNum As Long
For i = LBound(RowArr) To UBound(RowArr)
RndNum = WorksheetFunction.Floor((UBound(RowArr) - LBound(RowArr) + 1) * Rnd, 1) + LBound(RowArr)
tmp = RowArr(i)
RowArr(i) = RowArr(RndNum)
RowArr(RndNum) = tmp
Next i
'Calculate the number of rows to divvy up
Const LIMIT As Double = 0.1 '10%
Dim Size As Long
Size = WorksheetFunction.Ceiling((UBound(RowArr) - LBound(RowArr) + 1) * LIMIT, 1)
If Size > UBound(RowArr) Then Size = UBound(RowArr)
'Collect the chosen rows into a range
Dim TargetRows As Range
For i = LBound(RowArr) To LBound(RowArr) + Size
If TargetRows Is Nothing Then
Set TargetRows = Sheet1.Rows(RowArr(i))
Else
Set TargetRows = Union(TargetRows, Sheet1.Rows(RowArr(i)))
End If
Next i
'Define the Output Location
Dim OutPutRange As Range
Set OutPutRange = Sheet2.Cells(1, 1) 'Top Left Corner
'Copy the randomly chosen rows to the output location
TargetRows.Copy Destination:=OutPutRange.Resize(TargetRows.Rows.Count).EntireRow
End Sub

Create and loop a column which is based on the difference between a column and a cell

I need to create a column with the difference between a column and a cell (A3) in a loop.
In the picture I would for example like to know impact 1 with the H3 to a H.. = scenario(F3 to F...) - A3 and impact 2= Scenario2(G3...G)-A3 for x years (B3) for example.
I started with an if loop but I struggled to loop the whole column.
Sub Lab1()
Dim i As Integer
If i <= Range("B3").Value Then
Range("H3").Value = Range("F3").Value - Range("A3").Value
Range("J3").Value = Range("G3").Value - Range("A3").Value
End If
i = 2020 + Range("B5").Value
End Sub
I'm a little iffy on where column P from your code comes into play with your screenshot, but this should roughly do what you're looking for I think. Let us know if you run into any issues!
Sub loop1()
'define variables to work with
Dim ws As Worksheet
Dim interCol As Long, scen1Col As Long, impact1Col As Long
Dim firstRow As Long, lastRow As Long
Dim rng As Range
Dim intervention As Long, scenario As Long
Dim i As Long
'define current worksheet
Set ws = ActiveSheet
'define column numbers
interCol = 1 'A
scen1Col = 6 'F
impact1Col = 8 'H
'define start row
firstRow = 3
'end row is the last non-blank cell in Scenario 1 column
lastRow = ws.Cells(ws.Rows.Count, scen1Col).End(xlUp).Row
'loop from first row to last row
For i = firstRow To lastRow
'define cell to update
Set rng = ws.Cells(i, impact1Col)
'intervention doesn't change from row to row
intervention = ws.Cells(firstRow, interCol)
'scenario varies from row to row
scenario = ws.Cells(i, scen1Col)
'update target cell with calculation
rng = scenario - intervention
Next i
End Sub

Resize shape as per last filled column

I would like to change the width of the shape in this Excel in the attached picture. The size would be determined by the last column that contains data, in this case column E.
I have added the following code:
Sub UsedRange_Example_Column()
Dim LastColumn As Long
With ActiveSheet.UsedRange
LastColumn = .Columns(.Columns.Count).Column
End With
iCol = 0
For i = 3 To LastColumn
iCol = ActiveSheet.Cells(1, i).ColumnWidth + iCol
Next i
ActiveSheet.Shapes("Shape 37").Width = (iCol) * 5.72
End Sub
However, I am unable to determine the multiplier which I should use to change the size cause 5.72 is not giving me the correct results. Please note that column B is 1" in size.
Assuming your shape starts in col B, perhaps something like this. I have not specified the Top of the shape.
Sub UsedRange_Example_Column()
Dim LastColumn As Long
With ActiveSheet.UsedRange
LastColumn = .Columns(.Columns.Count).Column
End With
With ActiveSheet.Shapes("Shape 37")
.Left = Range("B1").Left
.Width = Range("B1").Resize(, LastColumn - 1).Width
End With
End Sub
You can set it to the width of your range in question:
Sub UsedRange_Example_Column()
Dim dataRng As Range, ws As Worksheet
Set ws = ThisWorkbook.Worksheets(1)
Set dataRng = ws.UsedRange
With ws.Shapes("Shape 37")
.Left = dataRng.Left
.Width = dataRng.Width
End With
End Sub
You should get out of the habit of using ActiveSheet whenever possible (most of the time it is). Always declare your worksheets as this can avoid many debugging nightmares.

Change column width and row height of hidden columns and rows (remaining hidden): Excel VBA

I have a macro which changes column width and row height of all the worksheets in my excel workbook, however, this macro is not making the changes in the hidden rows and column.
Please suggest how should I modify my code so that it should change the column width and row height of hidden rows and columns and keep them hidden?
Sub rowcolactivesheetb()
Dim exworkb As Workbook
Dim xlwksht As Worksheet
Dim lastrow1 As Long
Dim lastcolumn1 As Long
Dim firstrowDB As Long
With ActiveSheet
lastrow1 = .Cells(Rows.Count, "A").End(xlUp).Row
lastcolumn1 = .Cells(1, Columns.Count).End(xlToLeft).Column
.Range(.Cells(1, 1), .Cells(lastrow1, lastcolumn1)).Select
With Selection.SpecialCells(xlCellTypeVisible)
.ColumnWidth = 10.2
.RowHeight = 9.4
End With
End With
End Sub
Edit
I have implemented Wolfie's method below, but am now getting
Run-time error 91, Object variable or With block variable not set.
on this line:
' Z is a number, my loop variable for looping over each sheet
rng = ActiveWorkbook.Sheets(Z).Range(Sheets(Z).Cells(1, 3), Sheets(Z).Cells(lastrow1, lastcolumn1))
The below code is fairly straight-forward, and commented for further details. Steps:
Loop through rows and columns in the used range, note which ones are hidden.
Unhide everything and resize
Loop back through rows and columns, hiding those which were hidden before
Code:
Sub rowcolactivesheetb()
' Resizes all rows and columns, including those which are hidden.
' At the end, hidden rows and columns remain hidden.
Dim n As Long
Dim hiddencols() As Long
Dim hiddenrows() As Long
Dim rng As Range
Application.ScreenUpdating = False
With ThisWorkbook.ActiveSheet
' Set up range variable and true/false hidden arrays
' We don't need to find last row/col, just used UsedRange
Set rng = .UsedRange
ReDim hiddencols(rng.Columns.Count)
ReDim hiddenrows(rng.Rows.Count)
' Get hidden/visible status of each row and column
For n = 0 To UBound(hiddencols)
hiddencols(n) = rng.Columns(n + 1).Hidden
Next n
For n = 0 To UBound(hiddenrows)
hiddenrows(n) = rng.Rows(n + 1).Hidden
Next n
' Unhide all
rng.EntireColumn.Hidden = False
rng.EntireRow.Hidden = False
' resize all
rng.ColumnWidth = 10.2
rng.RowHeight = 9.4
' Re-hide rows/cols
For n = 0 To UBound(hiddencols)
rng.Columns(n + 1).Hidden = hiddencols(n)
Next n
For n = 0 To UBound(hiddenrows)
rng.Rows(n + 1).Hidden = hiddenrows(n)
Next n
End With
Application.ScreenUpdating = True
End Sub
Lastly a note on With, you should not start a second With block unless it is for an object within the first one. But really you could have ditched the (undesirable) Select using that fact anyway...
With ActiveSheet
lastrow1 = .Cells(Rows.Count, "A").End(xlUp).Row
lastcolumn1 = .Cells(1, Columns.Count).End(xlToLeft).Column
With .Range(.Cells(1, 1), .Cells(lastrow1, lastcolumn1)).SpecialCells(xlCellTypeVisible)
.ColumnWidth = 10.2
.RowHeight = 9.4
End With
End With
Edit:
With respect to your follow up error, you must use the Set command when assigning a Range object to a variable. So your code should be
Set rng = ActiveWorkbook.Range("...
You don't have to use Set for fundamental variable types (Strings, Integers, etc)

Resources