Follow-up to thread707-698561 . Thought I'd post this code (sorry about the length) for comment or for others to use. It's a function that, when passed a string like "A, D:F, B(12), K:M(8.5)" copies the values/formats in those columns to a new workbook and sets the column widths to the values in parentheses (if specified). Useful for creating simplified snapshot "views" of a complex spreadsheet for executives or salespeople (not that I have any experience with needing that! [ROFL]) Anyone care to suggest tweaks to this function?
Thanks!
VBAjedi![[swords] [swords] [swords]](/data/assets/smilies/swords.gif)
Code:
Function CopyCols(ColList, SourceSheet As Worksheet, TitleText)
' Copies columns to a new workbook, returns new workbook reference.
' ColList should be in the form "A, C(14),F, E, J:L (8),P"
' (spaces ignored before/after commas, multiple-column references
' like 'J:L' allowed, optional column widths in parentheses after letter)
' Columns MUST NOT contain merged cells (or column will be skipped)!
' This limitation could be bypassed by modifying code to copy
' a range like "A1:A1000" instead of the whole column
Dim ColArray(2, 200), FirstEmptyCol As Integer
Dim wsThis As Worksheet, wbNew As Workbook, wsNew As Worksheet
Dim x, y, z, a ' utility variables
If Len(ColList) = 0 Then Exit Function
' Parse ColList, store in two-dimensional array (Dimension 1=ColLetterRef, 2=ColWidth)
x = 1
y = 1
z = 0
Do
a = Mid(ColList, x, 1)
Select Case a
Case ",", "(", "" ' separator or end of list found
z = z + 1 ' column counter
ColArray(1, z) = Trim(Mid(ColList, y, (x - y)))
If InStr(1, ColArray(1, z), ":") < 1 Then ' Is a single-column reference
ColArray(1, z) = ColArray(1, z) & ":" & ColArray(1, z)
End If
x = x + 1 ' advance to start of next section (either width or next column)
y = x ' reset starting marker
If a = "(" Then ' a width was specified for this column
Do Until Mid(ColList, x, 1) = ")" Or Mid(ColList, x, 1) = ""
x = x + 1 ' advance to end of width bracket
Loop
ColArray(2, z) = Trim(Mid(ColList, y, (x - y))) ' store width in array
' In case there are spaces between ")" and "," :
Do Until Mid(ColList, x, 1) = "," Or Mid(ColList, x, 1) = ""
x = x + 1 ' advance to next column
Loop
x = x + 1 ' advance to start of next column section
y = x ' reset starting marker
End If
' Verify parser's results:
Debug.Print ColArray(1, z) & ", " & ColArray(2, z)
Case Else ' Keep looking for a separator or end of list
x = x + 1
End Select
Loop While x <= Len(ColList)
' Add workbook, copy column values/formats, and adjust column widths if specified
Set wsThis = SourceSheet
Set wbNew = Workbooks.Add
Set wsNew = wbNew.Worksheets(1)
x = 0
y = 0
FirstEmptyCol = 1
For i = 1 To z ' loop through ColArray
Do While Not ColumnIsEmpty(wsNew, FirstEmptyCol)
FirstEmptyCol = FirstEmptyCol + 1
Loop
' Copy column(s)
On Error Resume Next ' Copy causes error if column contains merged cells
wsThis.Columns(ColArray(1, i)).Copy
wsNew.Cells(1, FirstEmptyCol).PasteSpecial (xlPasteValues)
wsNew.Cells(1, FirstEmptyCol).PasteSpecial (xlPasteFormats)
On Error GoTo 0
' Now set column width(s)
If Len(ColArray(2, i)) > 0 Then ' a width was specified for this column
x = Selection.Columns.Count
For y = FirstEmptyCol To (FirstEmptyCol + x - 1) ' loop through pasted columns
wsNew.Columns(y).ColumnWidth = ColArray(2, i)
Next y
End If
FirstEmptyCol = FirstEmptyCol + 1
Next
If Len(TitleText) > 0 Then
wsNew.Rows(1).Insert
With wsNew.Range("A1") 'Cells(1, 1)
.Value = TitleText
.Font.Size = 14
.Font.Bold = True
.Font.Underline = True
End With
End If
Set CopyCols = wbNew
End Function
Function ColumnIsEmpty(Ws As Worksheet, ColNum As Integer) As Boolean
Dim r As Range
Set r = Ws.Cells(1, ColNum)
If IsEmpty(r) Then ' First cell is empty
Set r = r.End(xlDown) ' Returns row 65536 if no earlier cell has contents
If IsEmpty(r) Then ColumnIsEmpty = True ' Whole column is empty
End If
Set r = Nothing
End Function
Thanks!
VBAjedi
![[swords] [swords] [swords]](/data/assets/smilies/swords.gif)