I have a little problem with my macrocode, and need your advice. Here my base macrocode:
Option Explicit
Sub NurZumUeben()
'oberste Zeile löschen, fixieren und linksbündig ausrichten
Rows("1:1").Select
Selection.Delete Shift:=xlUp
With ActiveWindow
.SplitColumn = 0
.SplitRow = 1
End With
ActiveWindow.FreezePanes = True
'Jede zweite Zeile schattieren
Application.ScreenUpdating = False
Dim Zeile, ZeilenNr As Integer
With ActiveSheet.UsedRange.Rows
.Interior.ColorIndex = xlNone
.Borders.ColorIndex = xlNone
End With
ZeilenNr = 2
For Zeile = 2 To ActiveSheet.UsedRange.Rows.Count
With Rows(Zeile)
If .Hidden = False Then
If ZeilenNr Mod 2 = 0 Then
.Interior.ColorIndex = 15
.Borders.Weight = xlThin
.Borders.ColorIndex = 16
ZeilenNr = ZeilenNr + 1
Else
ZeilenNr = ZeilenNr + 1
End If
End If
End With
Next Zeile
Application.ScreenUpdating = True
'oberste Zeile einfärben
Rows("1:1").Select
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 65535
.TintAndShade = 0
.PatternTintAndShade = 0
End With
'Spalte_suchen&formatieren
Dim iLeSpa As Integer
Dim iSpalte As Integer
Dim bGefunden As Boolean
iLeSpa = IIf(IsEmpty(Cells(1, Columns.Count)), Cells(1, _
Columns.Count).End(xlToLeft).Column, Columns.Count)
For iSpalte = 1 To iLeSpa
If Cells(1, iSpalte).Value = "click_thru_pct" Then
bGefunden = True
Exit For
End If
Next iSpalte
If bGefunden Then
With Range(Cells(2, iSpalte), Cells(5000, iSpalte))
.Replace What:="%", Replacement:="", LookAt:=xlPart, SearchOrder:=xlByRows
Range("K1") = 100
Range("K1").Copy
.PasteSpecial Paste:=xlPasteAll, Operation:=xlDivide
.NumberFormat = "0.00%"
Range("K1").Clear
End With
Else
MsgBox "Die Überschrift ""click_thru_pct"" wurde nicht gefunden.", _
48, " Hinweis für " & Application.UserName
End If
End Sub
Once thank you all who can help. Unfortunately, I get the final formatting not go quite
Here are the results: example
I did not want to color the entire column but only the top row. In addition, the lower empty fields with ugly 0.00% formatted constantly.
Furthermore, I noticed that after the coloration of the first line, the field K1 is visible. That is with me unfortunately impractical because these Excel documents can also go differently in the row.
Here is the document on which you can test it if necessary.
example
Thank you very much
Change modular function to calculate the for loop variable. I see no purpose in using a separate variable for this. Change this:
ZeilenNr = 2
For Zeile = 2 To ActiveSheet.UsedRange.Rows.Count
With Rows(Zeile)
If .Hidden = False Then
If ZeilenNr Mod 2 = 0 Then
.Interior.ColorIndex = 15
.Borders.Weight = xlThin
.Borders.ColorIndex = 16
ZeilenNr = ZeilenNr + 1
Else
ZeilenNr = ZeilenNr + 1
End If
End If
End With
Next Zeile
To this:
For Zeile = 2 To ActiveSheet.UsedRange.Rows.Count
With Rows(Zeile)
If .Hidden = False Then
If Zeile Mod 2 = 0 Then
.Interior.ColorIndex = 15
.Borders.Weight = xlThin
.Borders.ColorIndex = 16
End If
End If
End With
Next Zeile
I apologize if I am missing something here. Also, I cannot view the examples you provided because the site requires a login and it is not in English. Sorry again.
Within your existing code,
Substitute 5000 with ActiveSheet.UsedRange.Rows.Count
Substitute Range("K1").Clear with Range("K1").ClearContents
Instead of For Zeile = 2 To ActiveSheet.UsedRange.Rows.Count, you could use
For Zeile = 2 To ActiveSheet.Range("A1").CurrentRegion.Rows.Count-1
.UsedRange is not always properly reset. You sample seems a good candidate for .CurrentRegion
Related
I'm relatively new to VBA, so thanks in advance for the advice. I am just dabbling to help out a friend to make his work less repetitive in my free time.
I created a GUI that has 2 ListBoxes that contain the names of the worksheets in the excel file. The left ListBox contains the available worksheets and the right ListBox is the list of worksheets the user chooses to perform the analysis on with the ability to move the names between the 2 ListBoxes. I am trying to link the GUI to my Module I created that performs the actual analysis. Once it is linked, I need the Selections that are made in the GUI to become an array that can be looped through in the Module. I am missing a few pieces, so bear with me please.
Submit Button Code:
Dim Size As Integer
Size = Me. ListBox2 . ListCount - 1
ReDim Selection(0 To Size) As String
Dim i As Integer
For i = 0 To Size
Selection (i) = Me.ListBox2.ItemData(i)
Next i
Unload GUI
The Area in the Module that I want to implement the Selection:
'Only performs copy/paste actions on the worksheets that aren't named "Summary".
For Each sh In ActiveWorkbook. Worksheets
If sh.Name < > DestSh.Name Then
'Sets the Range you want to Copy from the source Worksheets. This range is the set of cells with data in it.
Set CopyRng = sh. UsedRange
The goal is to read the Selections from the GUI, locate the sheet that the Selections are named after and link the selections to the "sh" variable somehow.
Since you are already referencing sh as a Worksheet variable in your code, while the Selections array holds strings, I believe the simplest way would be to shift the For..Each statement to:
For Each sel_item In Selection
and add the line:
Set sh = ActiveWorkbook.Worksheets(sel_item)
You will, of course, also need to edit the Next sh statement to Next sel_item, and add a Dim sel_item as Variant
In other words, the beginning of the loop section will look like:
'Only performs copy/paste actions on the worksheets that aren't named "Summary".
For Each sel_item In Selection
Set sh = ActiveWorkbook.Worksheets(sel_item)
If sh.Name < > DestSh.Name Then
'Sets the Range you want to Copy from the source Worksheets. This range is the set of cells with data in it.
Set CopyRng = sh. UsedRange
Instead of this (original):
'Only performs copy/paste actions on the worksheets that aren't named "Summary".
For Each sh In ActiveWorkbook. Worksheets
If sh.Name < > DestSh.Name Then
'Sets the Range you want to Copy from the source Worksheets. This range is the set of cells with data in it.
Set CopyRng = sh. UsedRange
Delimited Cell Expansion
First adjust the values in the constants section and then read through the whole comments because there might be some issues you wouldn't expect. You can use it on any column containing commas as delimiters, so in your case you can use it on the Base column, too.
Sub DelimitedCellExpansion()
Const cVntWsSource As String = "Sheet1" ' Source Worksheet Name/Index
Const cStrSourceFirst As String = "A1" ' Source First Cell Range of Data
Const cVntSplit As Variant = "D" ' Source Column Letter/Number
Const cVntWsTarget As String = "Sheet2" ' Target Worksheet Name/Index
Const cStrTargetFirst As String = "B1" ' Target First Cell Range of Data
Const cStrSep As String = ",,,|,,|, ," ' Wrong Separators
Dim vntSrc As Variant ' Source Array
Dim vntSep As Variant ' Separator Array
Dim vntSplitData As Variant ' Split Data Array
Dim vntSplit As Variant ' Split Array
Dim vntCol As Variant ' Target Column Array
Dim vntTgt As Variant ' Target Array
Dim intCol As Integer ' Source Array Target Column
Dim lng1 As Long ' Source Array Target Column Rows Count(er)
Dim int1 As Integer ' Separator Array Strings Counter
Dim lng2 As Long ' Target Array Rows Count(er)
Dim int2 As Integer ' Split Data Column Counter
' Source Worksheet Data Extraction
With ThisWorkbook.Worksheets(cVntWsSource)
If Not .Cells.Find("*", .Cells(.Rows.Count, .Columns.Count), -4123, , 1) _
Is Nothing Then ' Worksheet has data.
' Paste Source Range into Source Array
vntSrc = .Range(cStrSourceFirst, .Cells(.Cells.Find("*", , , , 1, 2) _
.Row, .Cells.Find("*", , , , 2, 2).Column))
' Calculate Source Array Target Column.
intCol = .Columns(cVntSplit).Column - .Range(cStrSourceFirst).Column + 1
Else ' Worksheet is empty.
GoTo EmptySheetErr
End If
End With
' Split Separator String into Separator Array.
vntSep = Split(cStrSep, "|")
' Introduce Split Data Array
ReDim vntSplitData(1 To UBound(vntSrc))
' Target Array Columns Count
For lng1 = 1 To UBound(vntSrc)
' Clean separators in current field of Target Column.
vntSrc(lng1, intCol) = WorksheetFunction.trim(vntSrc(lng1, intCol))
For int1 = 0 To UBound(vntSep)
vntSrc(lng1, intCol) = Replace(vntSrc(lng1, intCol), _
vntSep(int1), ",")
Next
' Split current field of Target Column.
vntSplit = Split(vntSrc(lng1, intCol), ",")
' Resize Target Column Array.
If Not IsEmpty(vntCol) Then
ReDim Preserve vntCol(1 To UBound(vntCol) + UBound(vntSplit) + 1)
Else
ReDim vntCol(1 To UBound(vntSplit) + 1)
End If
' Copy split values to Target Column Array.
For int1 = 0 To UBound(vntSplit)
vntCol(UBound(vntCol) - UBound(vntSplit) + int1) = trim(vntSplit(int1))
Next
' Collect Split Data.
vntSplitData(lng1) = UBound(vntSplit) + 1
Next
Erase vntSplit
Erase vntSep
' Write data to Target Array
lng2 = 1
ReDim vntTgt(1 To UBound(vntCol), 1 To UBound(vntSrc, 2))
For lng1 = 1 To UBound(vntSrc)
' Write current row of other columns to Target Array.
Select Case intCol
Case 1 ' LBound(vntSrc, 2)
For int1 = 2 To UBound(vntSrc, 2)
vntTgt(lng2, int1) = vntSrc(lng1, int1)
Next
Case UBound(vntSrc, 2)
For int1 = 1 To UBound(vntSrc, 2) - 1
vntTgt(lng2, int1) = vntSrc(lng1, int1)
Next
Case Else
For int1 = 1 To intCol - 1
vntTgt(lng2, int1) = vntSrc(lng1, int1)
Next
For int1 = intCol + 1 To UBound(vntSrc, 2)
vntTgt(lng2, int1) = vntSrc(lng1, int1)
Next
End Select
' Write current row of Source Array Target Column to Target Array.
For int2 = 1 To vntSplitData(lng1)
vntTgt(lng2, intCol) = vntCol(lng2)
lng2 = lng2 + 1
Next
Next
Erase vntCol
' With ThisWorkbook.Worksheets(cVntWsTarget)
' ' Paste Target Array into Target Worksheet.
' .Range(cStrTargetFirst).Resize(UBound(vntTgt), UBound(vntTgt, 2)) = vntTgt
' End With
' This would have been the end, if there was no formatting to do.
' Introducing a Range object.
Dim objRng As Range
Set objRng = ThisWorkbook.Worksheets(cVntWsTarget) _
.Range(cStrTargetFirst).Resize(UBound(vntTgt), UBound(vntTgt, 2))
'***************************************
' This is necessary if there are merged cells in the Target Range.
' This clears the whole Target Worksheet.
objRng.Parent.Cells.Clear
' This clears only the Target Range.
' objRng.Cells.Clear
'***************************************
' Paste Target Array into Target Range of Target Worksheet.
objRng = vntTgt
Erase vntTgt
With objRng
' Paste formatting from first row down to the last.
.Cells(1, 1).Resize(, .Columns.Count).Copy ' Copy first row.
.PasteSpecial Paste:=xlPasteFormats ' Paste formatting down to last.
' The Target Range is selected and is flickering. Therefore:
Application.CutCopyMode = False ' Target Range still selected.
'***********************************************************
' Apply formatting (merge)
'***********************************************************
' This is up to you. I have done only some easy formatting.
' With .Interior
' .ColorIndex = xlNone
' .Pattern = xlSolid
' .PatternColorIndex
' End With
' ' Font
' With .Font
' .Name = "Verdana"
' .Size = 10
' .Strikethrough = False
' .Superscript = False
' .Subscript = False
' .OutlineFont = False
' .Shadow = False
' .Underline = xlUnderlineStyleNone
' .ColorIndex = xlAutomatic
' .Bold = True
' End With
' Borders
With .Borders(xlEdgeLeft)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With .Borders(xlEdgeTop)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With .Borders(xlEdgeBottom)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With .Borders(xlEdgeRight)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With .Borders(xlInsideVertical)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With .Borders(xlInsideHorizontal)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
lng2 = 1
For lng1 = 1 To UBound(vntSrc)
' Write current row of other columns to Target Array.
Select Case intCol
Case 1 ' LBound(vntSrc, 2)
For int1 = 2 To UBound(vntSrc, 2): GoSub OtherFormat: Next
Case UBound(vntSrc, 2)
For int1 = 1 To UBound(vntSrc, 2) - 1: GoSub OtherFormat: Next
Case Else
For int1 = 1 To intCol - 1: GoSub OtherFormat: Next
For int1 = intCol + 1 To UBound(vntSrc, 2): GoSub OtherFormat: Next
End Select
GoSub TargetFormat
lng2 = lng2 + vntSplitData(lng1)
Next
Erase vntSplitData
Erase vntSrc
GoTo FormatEnd
'***********************************************************
' This is created to easily adjust (change) formatting.
' The formatting applies only to the Data range.
'***********************************************************
OtherFormat: ' Format other columns.
With .Cells(lng2, int1).Resize(vntSplitData(lng1))
If vntSplitData(lng1) > 1 Then ' Multiple rows.
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlCenter
.WrapText = False
.Orientation = 0
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = True
Else ' One row only.
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlBottom
.WrapText = False
.Orientation = 0
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = False
End If
End With
Return
TargetFormat: ' Format Target Column.
With .Cells(lng2, intCol).Resize(vntSplitData(lng1))
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlBottom
.WrapText = False
.Orientation = 0
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = False
End With
Return
FormatEnd:
' Only autofits the Target Range.
' .Columns.AutoFit
' Autofit from top.
.Columns.EntireColumn.AutoFit
'***********************************************************
End With
ProcedureExit:
Set objRng = Nothing
Exit Sub
EmptySheetErr:
MsgBox "You're in an empty sheet."
GoTo ProcedureExit
End Sub
Be gentle guys, I'm not a programmer.
I got this snippit of code off the internet many many moons ago. I would give credit, but I don't remember where it came from.
Sub Worksheet_SelectionChange(ByVal Target As Excel.Range)
Static xRow
Static xColumn
If xColumn <> "" Then
With Columns(xColumn)
.Interior.ColorIndex = xlNone
End With
With Rows(xRow)
.Interior.ColorIndex = xlNone
End With
End If
pRow = Selection.Row
pColumn = Selection.Column
xRow = pRow
xColumn = pColumn
With Columns(pColumn)
.Interior.ColorIndex = 19
.Interior.Pattern = xlSolid
End With
With Rows(pRow)
.Interior.ColorIndex = 19
.Interior.Pattern = xlSolid
End With
End Sub
The above code highlights rows and columns of a selected sell. The problem is that it highlights columns from 1 to 1048576, which causes the vertical scroll bar to get tiny. Plus if there is any color coding in the spreadsheet it screws that up. I decided to write my own highlighter. I put a border around my selected row,column and only do it for 500 rows. It works, almost. The problem is that something in my code cancels the copy command, and will not allow me to paste, which did not happen in the code above. Copy/Paste is a must. Any help would be greatly appreciated.
Sub Worksheet_SelectionChange(ByVal Target As Excel.Range)
Range("A1:N500").Borders(xlEdgeLeft).Weight = xlThin
Range("A1:N500").Borders(xlEdgeTop).Weight = xlThin
Range("A1:N500").Borders(xlEdgeBottom).Weight = xlThin
Range("A1:N500").Borders(xlEdgeRight).Weight = xlThin
Range("A1:N500").Borders(xlInsideVertical).Weight = xlThin
Range("A1:N500").Borders(xlInsideHorizontal).Weight = xlThin
Range("A1:N500").Borders(xlEdgeLeft).Color = vbBlack
Range("A1:N500").Borders(xlEdgeTop).Color = vbBlack
Range("A1:N500").Borders(xlEdgeBottom).Color = vbBlack
Range("A1:N500").Borders(xlEdgeRight).Color = vbBlack
Range("A1:N500").Borders(xlInsideVertical).Color = vbBlack
Range("A1:N500").Borders(xlInsideHorizontal).Color = vbBlack
Dim SplitAddress() As String
SplitAddress = Split(ActiveCell.Address, "$")
Dim RowSelection As String
RowSelection = "A" & SplitAddress(2) & ":" & "N" & SplitAddress(2)
Dim ColSelection As String
ColSelection = SplitAddress(1) & "1" & ":" & SplitAddress(1) & "500"
With Range(RowSelection)
.BorderAround Weight:=xlThick, Color:=RGB(255, 0, 0)
End With
With Range(ColSelection)
.BorderAround Weight:=xlThick, Color:=RGB(255, 0, 0)
End With
End Sub
try this.
it is work in progress
it copies the format, as the default format, from the very last cell in worksheet
the code uses no copy/paste to do the borders
i am still working on copy/paste between cells that you are having trouble with
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Application.ScreenUpdating = False
Dim aaa As DisplayFormat
Set aaa = Range("XFD1048576").DisplayFormat ' copy format from very last cell (it is a cheat)
Range("A1:N500").Borders.Color = aaa.Borders.Color ' revert border color to its default
Range("A1:N500").Borders.LineStyle = aaa.Borders.LineStyle
Dim i As Integer
For i = xlEdgeLeft To xlEdgeRight ' loop the four outside borders (7 to 10)
Target.EntireRow.Resize(1, 8).Borders.Item(i).Color = vbRed
Target.EntireRow.Resize(1, 8).Borders.Item(i).Weight = xlThick
Target.EntireColumn.Resize(500, 1).Borders.Item(i).Color = vbRed
Target.EntireColumn.Resize(500, 1).Borders.Item(i).Weight = xlThick
Next i
Application.ScreenUpdating = True
End Sub
I'm trying to add conditional formatting to a range that checks cell X1 and if it doesn't match it applies the conditions.
If i apply it to one cell it works great. however i need it applied to each cell in a range.
code:
Function FindComment(rng As Range, strSearch As String) As Boolean
On Error GoTo err_h:
strSearch = LCase(strSearch)
If Len(strSearch) = 0 Then
FindComment = False
Exit Function
End If
If InStr(1, rng.Comment.Text, strSearch, vbTextCompare) > 0 Or InStr(1, rng.Text, strSearch, vbTextCompare) > 0 Then
FindComment = False
Exit Function
End If
FindComment = True
Exit Function
err_h:
FindComment = True
End Function
And to apply the conditional formatting:
Public Sub AddConditionalFormat(rng As Range)
rng.FormatConditions.Add Type:=xlExpression, Formula1:= _
"=FINDCOMMENT(" & rng.Address(, , xlA1) & ",$X$1)"
rng.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority
With Selection.FormatConditions(1).Font
.ColorIndex = 2
End With
With rng.FormatConditions(1).Interior
.Pattern = xlGray75
.PatternThemeColor = xlThemeColorDark2
.PatternTintAndShade = 0
.ColorIndex = 2
.TintAndShade = 0
.PatternTintAndShade = 0
End With
rng.FormatConditions(1).StopIfTrue = False
End Sub
the range range("B6:GD9") are determined as rng.
currently if the results match it just blanks out all cells including the match.
anyone have an idea of how to easily fix? i'd prefer something that would not lag out the code by applying to each cell etc.
The Range.Address property defaults to absolute row and column references. You are looking for something like A1 but you are getting $A$1.
rng.FormatConditions.Add Type:=xlExpression, Formula1:= _
"=FINDCOMMENT(" & rng.Cells(1, 1).Address(RowAbsolute:=False, ColumnAbsolute:=False, ReferenceStyle:=xlA1) & ", $X$1)"
'alternate in shorthand
rng.FormatConditions.Add Type:=xlExpression, Formula1:= _
"=FINDCOMMENT(" & rng.Cells(1, 1).Address(0, 0, xlA1) & ", $X$1)"
Using .Cells(1, 1) should make that formula reference the upper left cell in rng.
I have an issue with my VBA code. I try to compare 2 columns, both A and B columns. If some data match, for example let's say that A2 contains text in B3, then I need to compare the cell C2 with the column D. I don't understand why but I get the error "End If without block If". Thanks a lot for you help guys.
Here is my code :
Sub Compare()
For i = 1 To 100
For j = 1 To 50
If InStr(1, ActiveSheet.Cells(i, 1).Value, ActiveSheet.Cells(j, 2).Value, vbTextCompare) <> 0 _
Then For k = 1 To 20
If InStr(1, ActiveSheet.Cells(i, 3).Value, ActiveSheet.Cells(k, 4).Value, vbTextCompare) <> 0 Then MsgBox i
End If
Next k
End If
Next j
Next i
End Sub
I found the structure of your if statements a bit confusing and I'm not entirely sure you can do a for loop as a one-liner like that to get rid of all the end ifs. For what it's worth, I think this code is a bit easier to follow:
Sub Compare()
For i = 1 To 100
For j = 1 To 50
If InStr(1, ActiveSheet.Cells(i, 1).Value, ActiveSheet.Cells(j, 2).Value, vbTextCompare) <> 0 Then
For k = 1 To 20
If InStr(1, ActiveSheet.Cells(i, 3).Value, ActiveSheet.Cells(k, 4).Value, vbTextCompare) <> 0 Then MsgBox i
Next k
End If
Next j
Next i
End Sub
This runs w/o a compile error, but can't comment if it does what you want it to do.
sous2817 raised an interesting question in their answer about whether or not a 1-line statement works if the body of the if statement is itself a for-loop. The answer appears to be "no" -- unless the for-loop itself is squeezed onto one line by using the colon statement separator:
Sub test1() 'compile error
Dim i As Long, s As Long
If i = 0 _
Then For i = 1 To 10
s = s + i
Next i
MsgBox s
End Sub
Sub test2() 'compiles okay
Dim i As Long, s As Long
If i = 0 _
Then For i = 1 To 10: s = s + i: Next i
MsgBox s
End Sub
If statements on one line don't need the End If statement.
End If without block If
Sub comparison()
For i = 2 To 1000
For j = 2 To 1000
If Worksheets(Worksheet).Range("A" & i).Value = Worksheets(Worksheet).Range("L" & j).Value Then
Worksheets(worksheet).Range("N" & j).Select
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 65535
.TintAndShade = 0
.PatternTintAndShade = 0
End With
End If
Next j
Next i
End Sub
I have multiple Excel files with the following structure:
Each file has the exact same columns (Apples, Oranges, Bananas, etc.) but placed under different letters throughout the sheets. For example, column "Apples" is under letter A in the first 5 sheets, but it's under letter C in the rest of the sheets. This order is not consistent and varies in each file.
I would like a macro capable of:
Unwrap all the cells in all sheets.
Hide columns from A to Z in all sheets.
Unhide only three columns featuring the words "apples/apple", "oranges/orange" and "bananas/bananas" in row 1.
Shrink to fit the text in the "apples/apple" column and set the width to 120.
Wrap to fit the text on the "oranges/orange" and "bananas/bananas" columns and set the width to 350.
Zoom all sheets to 100%.
I have this macro that works like a charm, as it allows me to choose which three columns I want to keep. However, it works exclusively if they are placed in the exact same order in all sheets:
Sub AdjustTF()
ColumnWidth = 10
ActiveWindow.Zoom = 100
Dim wsh As Worksheet
Dim rng As Range
Dim i As Long
Dim f As Boolean
Dim c As Long
On Error GoTo ErrHandler
' The following two lines are optional
Worksheets(1).Select
Range("A1").Select
For Each wsh In Worksheets
wsh.Cells.WrapText = False
wsh.Cells.VerticalAlignment = xlBottom
wsh.Cells.HorizontalAlignment = xlLeft
wsh.Cells.EntireColumn.Hidden = False
If f = False Then
Set rng = Application.InputBox( _
Prompt:="Select the columns to keep.", _
Type:=8).EntireColumn
f = True
End If
Set rng = wsh.Range(rng.Address).EntireColumn
c = wsh.Cells.Find(What:="*", SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious).Column
wsh.Range(wsh.Cells(1, 1), wsh.Cells(1, c)).EntireColumn.Hidden = True
With rng
.Hidden = False
With .Areas(1)
.ColumnWidth = 3
For i = 1 To 3
.ColumnWidth = 120 / .Width * .ColumnWidth
Next i
.ShrinkToFit = True
End With
With .Areas(2)
.ColumnWidth = 8
For i = 1 To 3
.ColumnWidth = 350 / .Width * .ColumnWidth
Next i
.WrapText = True
End With
With .Areas(3)
.ColumnWidth = 8
For i = 1 To 3
.ColumnWidth = 350 / .Width * .ColumnWidth
Next i
.WrapText = True
End With
End With
wsh.Cells.EntireRow.AutoFit
NextSheet:
Next wsh
Application.Goto Worksheets(1).Range("A1"), True
Exit Sub
ErrHandler:
Select Case Err
Case 424 ' Object required
Resume NextSheet
Case Else
MsgBox Err.Description, vbExclamation
End Select
End Sub
EDIT: I've also this code, which is significantly lighter (even though doesn't quite perform all tasks I wanted) but for some reasons works only with a single file and not when assigned to my Personal.xls sheet.
Sub AdjustTFAlternate()
Dim R As Range
Dim Ws As Worksheet
Dim Item
'In each worksheet
For Each Ws In ActiveWorkbook.Worksheets
'Hide all columns
Ws.UsedRange.EntireColumn.Hidden = True
'Search for this words
For Each Item In Array("apple*", "orange*", "banana*")
'Search for a keyword in the 1st row
Set R = Ws.Rows(1).Find(Item, LookIn:=xlFormulas, LookAt:=xlWhole)
If R Is Nothing Then
'Not found
Exit For
End If
'Unhide this column
R.EntireColumn.Hidden = False
Next
Next
End Sub
If you simply want a popup box for the user to select the 3 columns on each sheet, remove the line that reads
f = True
that is inside the If f = False Then statement.
If you want the macro to "remember" the column headers for each column chosen on the first page, then you'll need to modify the code slightly (and make some assumptions):
Assumptions
The column headers are in the first row
The column headers are unique (i.e., you don't have the same column title multiple times in the same sheet).
EDIT:
Code will now store all selected columns in an array that will search on each worksheet. For example, if on worksheet 1 you have apple, banana, and coconut, you will get an initial InputBox. If on worksheet 3, you now have apples, bananas, and coconuts, then you will get a second InputBox asking for these values. Now, on worksheets 4-n, the code will search for either apple or apples.
Code
Sub AdjustTF()
ColumnWidth = 10
Dim wsh As Worksheet
Dim rng As Range
Dim i As Long
Dim f As Boolean
Dim c As Long
'Dim aCol(1 To 1, 1 To 3) As String
Dim aCol() As String
ReDim aCol(1 To 3, 1 To 1)
Dim iCol(1 To 3) As Integer
Dim iTemp As Integer
Dim uStr As String
On Error GoTo ErrHandler
' The following two lines are optional
Worksheets(1).Select
Range("A1").Select
For Each wsh In Worksheets
d = 1
wsh.Cells.WrapText = False
wsh.Cells.VerticalAlignment = xlBottom
wsh.Cells.HorizontalAlignment = xlLeft
wsh.Cells.EntireColumn.Hidden = False
If f = False Then
On Error Resume Next
Err.Number = 0
Set rng = Application.InputBox( _
Prompt:="Select the columns to keep.", _
Type:=8).EntireColumn
If Err.Number > 0 Then
Exit Sub
End If
On Error GoTo ErrHandler
f = True
aCol(1, 1) = wsh.Cells(1, rng.Areas(1).Column).Value
aCol(2, 1) = wsh.Cells(1, rng.Areas(2).Column).Value
aCol(3, 1) = wsh.Cells(1, rng.Areas(3).Column).Value
Else
On Error Resume Next
For a = 1 To 3
iCol(a) = 0
Next
For a = 1 To UBound(aCol, 2)
Err.Number = 0
iTemp = wsh.Cells.Find(what:=aCol(1, a), lookat:=xlWhole).Column
If Err.Number = 0 And iCol(1) = 0 Then iCol(1) = iTemp
Err.Number = 0
iTemp = wsh.Cells.Find(what:=aCol(2, a), lookat:=xlWhole).Column
If Err.Number = 0 And iCol(2) = 0 Then iCol(2) = iTemp
Err.Number = 0
iTemp = wsh.Cells.Find(what:=aCol(3, a), lookat:=xlWhole).Column
If Err.Number = 0 And iCol(3) = 0 Then iCol(3) = iTemp
If iCol(1) > 0 And iCol(2) > 0 And iCol(3) > 0 Then Exit For
Next
If iCol(1) = 0 Or iCol(2) = 0 Or iCol(3) = 0 Then
wsh.Activate
Err.Number = 0
Set rng = Application.InputBox( _
Prompt:="Select the columns to keep.", _
Type:=8).EntireColumn
If Err.Number > 0 Then
Exit Sub
End If
a = UBound(aCol, 2) + 1
ReDim Preserve aCol(1 To 3, 1 To a)
aCol(1, a) = wsh.Cells(1, rng.Areas(1).Column).Value
aCol(2, a) = wsh.Cells(1, rng.Areas(2).Column).Value
aCol(3, a) = wsh.Cells(1, rng.Areas(3).Column).Value
Else
uStr = Range(wsh.Cells(1, iCol(1)), wsh.Cells(1, iCol(1))).Address & "," & _
Range(wsh.Cells(1, iCol(2)), wsh.Cells(1, iCol(2))).Address & "," & _
Range(wsh.Cells(1, iCol(3)), wsh.Cells(1, iCol(3))).Address
Set rng = Range(uStr)
End If
On Error GoTo ErrHandler
End If
Set rng = wsh.Range(rng.Address).EntireColumn
c = wsh.Cells.Find(what:="*", SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious).Column
wsh.Range(wsh.Cells(1, 1), wsh.Cells(1, c)).EntireColumn.Hidden = True
With rng
.Hidden = False
With .Areas(1)
.ColumnWidth = 3
For i = 1 To 3
.ColumnWidth = 120 / .Width * .ColumnWidth
Next i
.ShrinkToFit = True
End With
With .Areas(2)
.ColumnWidth = 8
For i = 1 To 3
.ColumnWidth = 350 / .Width * .ColumnWidth
Next i
.WrapText = True
End With
With .Areas(3)
.ColumnWidth = 8
For i = 1 To 3
.ColumnWidth = 350 / .Width * .ColumnWidth
Next i
.WrapText = True
End With
End With
wsh.Cells.EntireRow.AutoFit
wsh.Activate
ActiveWindow.Zoom = 100
wsh.Cells(1, 1).Select
NextSheet:
Next wsh
Application.Goto Worksheets(1).Range("A1"), True
Exit Sub
ErrHandler:
Select Case Err
Case 424 ' Object required
Resume NextSheet
Case Else
MsgBox Err.Description, vbExclamation
End Select
End Sub