(without affecting the char level formatting in the cell)
I've already posted a similar question, but I unfortunately I realized I couldn't use any of the solutions because all of them removed all the formatting in the cells :(
I have a code that replaces various text strings. It looks like this (+ some more IFs):
Sub Fix()
Dim X As Long, Cell As Range
For Each Cell In Selection
For X = Len(Cell.Text) To 1 Step -1
If Cell.Characters(X, 3).Text = ", ," Then Cell.Characters(X, 3).Text = ","
If Cell.Characters(X, 3).Text = ", (" Then Cell.Characters(X, 3).Text = " ("
If Cell.Characters(X, 3).Text = ", [" Then Cell.Characters(X, 3).Text = " ["
If Cell.Characters(X, 3).Text = ", -" Then Cell.Characters(X, 3).Text = " -"
If Cell.Characters(1, 3).Text = "abc" Then Cell.Characters(1, 3).Text = ""
Next
Next
End Sub
The last line of my code deletes abc if this is contained at the beginning of the selected cell(s).
I am looking to find out how to delete abc when this is contained at the end of the selected cell(s).
But it's really important for me to preserve all the original formatting in the cells (text size, colors, bold/italic/underline letters etc).
Please bear in mind that I am a complete beginner and I don't know anything about programming. I've copied the code above from the internet and just changed the values.
Thank you in advance for your help.
Replace Characters (Preserve Formatting)
Option Explicit
Sub FixIt()
Const NoC As Long = 3
Const Special As String = "abc"
Dim Source As Variant: Source = Array(", ,", ", (", ", [", ", -")
Dim Target As Variant: Target = Array(",", " (", " [", " -")
Dim Cell As Range
Dim UB As Long: UB = UBound(Source)
Dim i As Long, x As Long
Dim Current As String
For Each Cell In Selection
Current = Cell.Characters(Len(Cell.Text) - NoC + 1, NoC).Text
If Current = Special Then _
Cell.Characters(Len(Cell.Text) - NoC + 1, NoC).Delete
For x = Len(Cell.Text) - NoC + 1 To 1 Step -1
GoSub replaceCurrent
Next
Next
Exit Sub
replaceCurrent:
Current = Cell.Characters(x, NoC).Text
For i = 0 To UB
If Current = Source(i) Then Current = Target(i): Exit For
Next
If i <= UB Then Cell.Characters(x, NoC).Text = Current
Return
End Sub
If you want to remove the last three characters of a cell if they are abc, then:
Before:
the code:
Sub EasyAsABC()
Dim s As String, L As Long
With ActiveCell
s = .Text
L = Len(s)
If Right(s, 3) = "abc" Then
.Characters(L, 1).Text = ""
.Characters(L - 1, 1).Text = ""
.Characters(L - 2, 1).Text = ""
End If
End With
End Sub
and after:
Something like this would probably work:
Sub FixData()
Dim X As Long, Y As Long, Cell As Range, FindChars As Variant, ReplaceChars As Variant, StartRemove As Variant, EndRemove As Variant
FindChars = Array(", ,", ", (", ", [", ", -") 'must have at least 2 elements, if you only have one then just put something it will never have like "zzzzzzzzzz"
ReplaceChars = Array(",", " (", " [", " -") 'must have at least 2 elements, if you only have one then just put something it will never have like "zzzzzzzzzz"
StartRemove = Array("something1", "somthingelse1") 'must have at least 2 elements, if you only have one then just put something it will never have like "zzzzzzzzzz"
EndRemove = Array("something2", "somthingelse2") 'must have at least 2 elements, if you only have one then just put something it will never have like "zzzzzzzzzz"
For Each Cell In Selection
For Y = LBound(FindChars) To UBound(FindChars)
If InStr(1, Cell.Text, FindChars(Y)) > 0 Then Cell.Characters(InStr(1, Cell.Text, FindChars(Y)), Len(FindChars(Y))).Delete
Next
For Y = LBound(StartRemove) To UBound(StartRemove)
If Left(Cell.Text, Len(StartRemove(Y))) = StartRemove Then Cell.Characters(1, Len(StartRemove(Y))).Delete
Next
For Y = LBound(EndRemove) To UBound(EndRemove)
If Right(Cell.Text, Len(EndRemove(Y))) = EndRemove Then Cell.Characters(Len(Cell) - Len(EndRemove(Y)) + 1, Len(EndRemove(Y))).Delete
Next
Next
End Sub
Edit based on conversations since and updates to reflect these conversations.
This code has 4 arrays, it rips through the find and replace arrays first to find and replace any instance. Then it goes through the start array to find only things at the start then lastly it loops the end array to find anything at the end of the string.
Using cell.characters().delete will remove those chars without altering the individual character formatting around it.
Since all your strings are length of 3, you simply need to adjust your loop:
For X = Len(Cell.Text) - 2 To 1 Step -1
Just add a line like:
If Cell.Characters(X, 3).Text = "abc" Then Cell.Characters(X, 3).Text = ""
That would make your last line loking for abc redundant and can be removed. However, it seems you could also use some other construct alltogether if you like too, possibly:
Sub Fixt()
Dim X As Long, Cell As Range
Dim arr1 As Variant: arr1 = Array("abc", ", ,", ", (", ", [", ", -")
Dim arr2 As Variant: arr2 = Array("", ",", " (", ", [", " -")
For Each Cell In Selection
For X = Len(Cell.Text) - 2 To 1 Step -1
Match = Application.Match(Cell.Characters(X, 3).Text, arr1, 0)
If IsNumeric(Match) Then Cell.Characters(X, 3).Text = arr2(Match - 1)
Next
Next
End Sub
Try,
Sub test()
Dim rngDB As Range, rng As Range
Dim i As Integer, x As Integer
Dim vWhat As Variant, vReplace As Variant
Dim s As String
Set rngDB = Selection
vWhat = Array("abc", ", ,", ", (", ", [", ", -")
vReplace = Array("", ",", " (", " [", " -")
For Each rng In rngDB
x = Len(rng) - 2
s = rng
If x > 0 Then
For i = 0 To UBound(vWhat)
If Mid(s, x, 3) = vWhat(i) Then
rng.Characters(x, 3).Text = vReplace(i)
End If
Next i
End If
Next rng
End Sub
Related
A separate program that I cannot change adds to a spreadsheet and sometimes it duplicates something.
For example:in cell 5, 3
ABC, vbd, S19M-0027757-27760, S19M-0027757-27760(1)
or it could be
ABC, vbd S19M-0027757-27760, S19M-0027757-27760(1)
What I need to do is replace both of them with S19M-0027757-27760(1) so the out come would be:
ABC, vbd, S19M-0027757-27760(1)
So far I have:
For i = 5 To lRow
inputArray = Split(Cells(i, 3).Value, " ")
For j = 0 To (UBound(inputArray) - LBound(inputArray) - 1)
Dim firstString As String
Dim secondString As String
firstString = inputArray(j)
secondString = inputArray(j + 1)
Next
Next
I am thinking the next step would be to compare letter by letter? But what about the comma and (1)?
Try this. Possibly not enough examples to be sure it will work in all cases, but a short test worked.
Sub x()
Dim i As Long, inputArray, j As Long, outputArray(), k As Long
For i = 1 To 3
inputArray = Split(Cells(i, 3).Value, ", ")
For j = LBound(inputArray) To UBound(inputArray)
k = k + 1
ReDim Preserve outputArray(1 To k)
If j = UBound(inputArray) - 1 Then
If inputArray(j + 1) Like inputArray(j) & "(*)" Then
outputArray(k) = inputArray(j + 1)
Exit For
Else
outputArray(k) = inputArray(j)
End If
Else
outputArray(k) = inputArray(j)
End If
Next j
Cells(i, 4).Value = Join(outputArray, ", ")
Erase outputArray: k = 0
Next i
End Sub
Some other way, possible through RegEx:
Sub Test()
Dim RegEx As Object: Set RegEx = CreateObject("VBScript.RegExp")
RegEx.Global = True
RegEx.Pattern = "([A-Z0-9-]{18})(?=.+\1)"
Dim lr As Long, x As Long
With Sheet1
lr = .Cells(.Rows.Count, 3).End(xlUp).Row
For x = 5 To lr
.Cells(x, 3).Value = Replace(Replace(RegEx.Replace(.Cells(x, 3).Value, ""), ", ,", ", "), " ,", ", ")
Next x
End With
End Sub
I agree with #SJR, some more examples would be great to know if the RegEx.Pattern would hold TRUE. I now went with the assumptions of 18-char patterns. It would hold for the current sample data:
Before:
After:
I was trying to create a universal, error resistant VBA code that would count words in selected ranges as MS Word does. This below is the best I could do and I was hoping that somebody would have a look and let me know if I missed something or suggest any improvements. The code is quite fast and works with single cell, non-adjacent cells and whole columns, I need it to be as universal as possible. I'll be looking forward to feedback.
Option Explicit
Sub word_count()
Dim r() As Variant 'array
Dim c As Long 'total counter
Dim i As Long
Dim l As Long 'string lenght
Dim c_ch As Long 'character counter
Dim c_s As String 'string variable
Dim cell As range
Dim rng As range
If Selection Is Nothing Then
MsgBox "Sorry, you need to select a cell/range first", vbCritical
Exit Sub
ElseIf InStr(1, Selection.Address, ":", vbTextCompare) = 0 And InStr(1, Selection.Address, ",", vbTextCompare) = 0 Then 'for when only one cell is selected
word_count_f Selection.Value, c
MsgBox "Your selected cell '" & Replace(Selection.Address, "$", "") & "' in '" & Selection.Parent.Name & "' has " & c & " words."
Exit Sub
ElseIf InStr(1, Selection.Address, ",", vbTextCompare) > 0 Then 'when user selects more than one cell by clicking one by one -> address looks like ('A1,A2,A3') etc
Application.ScreenUpdating = False
Dim help() As Variant
ReDim help(1 To Selection.Cells.Count)
i = 1
For Each cell In Selection 'loading straigh to array wouldn't work, so I create a helper array
help(i) = cell.Value
i = i + 1
Next cell
r = help
Else 'load selection to array to improve speed
Application.ScreenUpdating = False
r = Selection.Value
End If
Dim item As Variant
For Each item In r
word_count_f item, c
Next item
MsgBox "Your selected range '" & Replace(Selection.Address, "$", "") & "' in '" & Selection.Parent.Name & "' has " & c & " words."
End Sub
Private Function word_count_f(ByVal item As Variant, ByRef c As Long)
Dim l As Long 'lenght variable
Dim c_s As String 'whole string variable
Dim c_ch As Long 'characted count variable
l = Len(item)
If l = 0 Then Exit Function
c_s = item
c_s = Trim(c_s)
Do While InStr(1, c_s, " ", vbTextCompare) > 0 'remove double spaces to improve accuracy
c_s = Replace(c_s, " ", " ")
Loop
If InStr(1, c_s, " ", vbTextCompare) = 0 And l > 0 Then 'if there was just one word in the cell
c = c + 1
ElseIf InStr(1, c_s, " ", vbTextCompare) > 0 Then 'else loop through string to count words
For c_ch = 1 To l 'loop through charactes of the string
If (Mid(c_s, c_ch, 1)) = " " Then
c = c + 1 'for each word
End If
Next c_ch
c = c + 1 'add one for the first word in cell
Else 'hopefully useless msgbox, but I wanted to be sure to inform the user correctly
MsgBox "Sorry, there was an error while processing one of the cells, the result might not be accurate", vbCritical
End If
End Function
You can achieve this in a similar way but with less code if you are interested to see?:
Sub word_count()
start_time = Timer
Dim r As Variant 'temp split array
Dim arr As Variant 'array
Dim c As Long 'total counter
If Selection Is Nothing Then
MsgBox "Sorry, you need to select a cell/range first", vbCritical
Exit Sub
Else
c = 0
For Each partial_selection In Split(Selection.Address, ",")
If Range(partial_selection).Cells.Count > 1 Then
arr = Range(partial_selection).Value
Else
Set arr = Range(partial_selection)
'single cell selected don't convert to array
End If
For Each temp_cell In arr
If Len(Trim(temp_cell)) > 0 Then
r = Split(temp_cell, " ")
For Each temp_word In r
If Len(Trim(temp_word)) > 0 Then
c = c + 1
'If the word is just a blank space don't count
End If
Next
'c = c + (UBound(r) - LBound(r) + 1)
'trimmed = Trim(temp_cell)
'c = c + 1 + (Len(trimmed) - Len(Replace(trimmed, " ", "")))
Else 'Blank cell
'Do nothing
End If
Next
Next
End If
Dim item As Variant
time_taken = Round(Timer - start_time, 3)
MsgBox "Your selected range '" & Replace(Selection.Address, "$", "") _
& "' in '" & Selection.Parent.Name & "' has " & c & " words." _
& vbNewLine & "Time Taken: " & time_taken & " secs"
Debug.Print c & " in "; time_taken; " secs"
End Sub
You could try this sort of approach? There may be the need to check for the next character to the space being another space, which would need some additions made. To detect word one as being the same as word one in the count. Also, transferring the range to an array would make it a touch faster.
Function Word_Count(rng As Excel.Range) As Long
Dim c As Excel.Range
Dim s As String
Dim l As Long
For Each c In rng.Cells
s = Trim(c.Value)
If s <> "" Then
If InStr(1, s, " ") > 0 Then
' Find number of spaces. You can use the ubound of split maybe here instead
l = l + (Len(s) - Len(Replace(s, " ", "")))
Else
End If
' Will always be 1 word
l = l + 1
End If
Next c
Word_Count = l
Set c = Nothing
End Function
I need to find a string pattern of varying length and add a comma and space after that string pattern. For example, Search for the string "Cat. 123" I want to replace that string with the value "Cat. 123, " (i.e. add a comma and then a space at the end of "Cat. 123"). I am using Mac Office 2011 so any code has to work with the Mac version of Excel.
I've tried using Replace.Regex, Split and all other Replace functions I could find. The code below is the best I have come up with in order to do this but it's not adding the comma and the space to the end of the string pattern.
Sub test()
Dim r As Range, x, y
Set r = Cells.Find("?*, Cat. *", , , 1)
If Not r Is Nothing Then
Do
' Search for any string with the pattern Cat. 123, Cat. 14, etc
x = Split(r.Value, " Cat. ")
If x(UBound(x)) Like "* *" Then
' Replace string Cat. 123 with the new string Cat. 123,
y = Split(x(UBound(x)))
x(0) = "Cat. " & y(0) & ", " & x(0)
x(UBound(x)) = y(1)
Else
y = x(UBound(x))
x(0) = "Cat. " & y & ", " & x(0)
x(UBound(x)) = ""
End If
r.Value = Join(x)
Set r = Cells.FindNext(r)
Loop Until r Is Nothing
End If
End Sub
So the output of each cell that contains a pattern like the following examples: "Cat. 123" "Cat. 1" "Cat. 34" "Cat. 4567", would be changed to "Cat. 123, " "Cat. 1, " "Cat. 34, " "Cat. 4567, " NOTE: The original string will always have a period after the word "Cat" and will then be followed by a space and then followed with a single digit all the way up to four digits as shown above.
Give this a try (this time without vbscript dependent regex):
Sub tgr()
Dim aData As Variant
Dim sTemp As String
Dim lCatLoc As Long
Dim lNextSpace As Long
Dim i As Long, j As Long
With ActiveSheet.UsedRange
If .Cells.Count = 1 Then
ReDim aData(1 To 1, 1 To 1)
aData(1, 1) = .Value
Else
aData = .Value
End If
For i = 1 To UBound(aData, 1)
For j = 1 To UBound(aData, 2)
If Len(aData(i, j)) > 0 Then
If aData(i, j) Like "*Cat. [0-9]*" Then
lCatLoc = InStr(1, aData(i, j), "Cat. ", vbTextCompare)
lNextSpace = InStr(lCatLoc + 5, aData(i, j) & " ", " ", vbTextCompare)
sTemp = Mid(aData(i, j), lCatLoc, lNextSpace - lCatLoc)
If Right(sTemp, 1) <> "," Then aData(i, j) = Replace(aData(i, j), sTemp, sTemp & ", ")
End If
End If
Next j
Next i
.Value = aData
End With
End Sub
I am facing problem when receiving a long message as below
40=1.22.50=0.002.60=35.
The system use the dot as separator while there is also decimal values for numeric value.
The desired output is
40=1.22
50=0.002
60=35
I am now using manual way to format the message. Hope to have a better way to overcome this.
Assuming you have one dot "." as the decimal position, and another "." that separates each element in the array. You can use the code below to read all values of the Long string into an array (Nums is the name of the array).
Option Explicit
Sub Seperate_DecimNumbers()
Dim Nums As Variant
Dim FullStr As String
Dim DotPosition As Integer
Dim i As Integer
' init array size to a large size , will redim it at the end to number of elements found
ReDim Nums(1 To 100)
FullStr = "40=1.22.50=0.002.60=35."
i = 1 ' init array elements counter
Do Until Len(FullStr) = 0
' call FindN function , searching for the 2nd "."
DotPosition = FindN(FullStr, ".", 2)
' unable to find 2 "." in the string >> last element in the array
If DotPosition = 0 Then
Nums(i) = FullStr
Exit Do
Else ' was able to find 2 "." in the string
Nums(i) = Left(FullStr, DotPosition - 1)
End If
i = i + 1
FullStr = Right(FullStr, Len(FullStr) - DotPosition)
Loop
' redim array back to maximum of numbers found in String
ReDim Preserve Nums(1 To i)
' place output start location from Range A2 and below (till number of elements in the array)
Range("A1").Offset(1, 0).Resize(UBound(Nums), 1).Value = Application.Transpose(Nums)
End Sub
Function FindN(sInputString As String, sFindWhat As String, N As Integer) As Integer
' this function find the Nth position of a certain character in a string
Dim J As Integer
Application.Volatile
FindN = 0
For J = 1 To N
FindN = InStr(FindN + 1, sInputString, sFindWhat)
If FindN = 0 Then ' unable to find the 2nd "." >> last appearance
Exit For
End If
Next
End Function
See result below:
Here's my take on the answer, which splits things on the = rather than the .. Doing it this way allows for input such as 40=1.22.50=0.002.60=35.70=120. (i.e. the part to the right of an = does not have to contain a ., it could be an integer.)
Sub SplitDotEqual()
Dim s As String
Dim a() As String
Dim i As Integer
Dim d As Integer
'Read from A1
s = Range("A1").Value
'Split on the "="
a = Split(s & ".", "=") ' include an extra "." to ensure that
' the final field is ended
For i = 0 To UBound(a) - 1
'Put the "=" back
a(i) = a(i) & "="
'Find the last "." before the next "="
d = InStrRev(a(i + 1), ".")
'Append everything prior to the "."
a(i) = a(i) & Left(a(i + 1), d - 1)
'Write to A2:Ax
Cells(i + 2, 1).Value = a(i)
'Strip off everything prior to the ".",
'leaving just the stuff prior to the "="
a(i + 1) = Mid(a(i + 1), d + 1)
Next
End Sub
Let's assume that every other dot is a separator. This code changes the odd-numbered dots into pipes and then parses on the pipes:
Sub parser()
Dim FlipFlop As Boolean, dot As String, pipe As String
Dim s As String, L As Long, i As Long, CH As String
dot = "."
pipe = "|"
s = Range("A1").Value
L = Len(s)
FlipFlop = True
For i = 1 To L
CH = Mid(s, i, 1)
If CH = dot Then
If FlipFlop Then
Else
Mid(s, i, 1) = pipe
End If
FlipFlop = Not FlipFlop
End If
Next i
msg = s & vbCrLf
ary = Split(s, pipe)
For Each a In ary
msg = msg & vbCrLf & a
Next a
MsgBox msg
End Sub
got more closer message and the code partially works.
8=TEST.1.2.9=248.35=D.49=MMUIJ.56=FGTUH.34=32998.50=MMTHUJ.57=AY/ABCDE.52=20161216-07:58:07.11=00708991.1=A-12345-
I have an excel file written in this way:
187712 201 37 0.18
2525 580 149 0.25
136829 137 43 0.31
I need to export this file with same spaces, same formatting in a txt file. How can i do it? I've tryied Save As | Formatted Text (Space Delimited) (*.prn) but not working because i have an issue on the last column. Is there a macro? Thanks.
EDIT: i tryied a macro:
Sub TEST()
Dim c As Range, r As Range
Dim output As String
For Each r In Range("A1:L504").Rows
For Each c In r.Cells
output = output & " " & c.Value
Next c
output = output & vbNewLine
Next r
Open "D:\MyPath\text.txt" For Output As #1
Print #1, output
Close
End Sub
but the result is
187712 201 37 0.18
2525 580 149 0.25
136829 137 43 0.31
These values are only an example because there are about 504 columns!! Anyway the problem is that if in the first column there is a value shorter then the others it lost the formatting like the second row as you can see.
Your posted data shows fixed fields with field-widths of 8,7,7,4 (each field is a combination of characters and trailing blanks). These can be adjusted as necessary in the macro below. Also adjust the folder name to suit your needs:
Sub FixedField()
Dim fld(1 To 4) As Long
Dim V(1 To 4) As String
Dim N As Long, L As Long
Dim K As Long
fld(1) = 8
fld(2) = 7
fld(3) = 7
fld(4) = 4
N = Cells(Rows.Count, "A").End(xlUp).Row
Close #1
Open "c:\TestFolder\test.txt" For Output As #1
For L = 1 To N
outpt = ""
For K = 1 To 4
V(K) = Cells(L, K).Text
While Len(V(K)) <> fld(K)
V(K) = V(K) & " "
Wend
outpt = outpt & V(K)
Next K
MsgBox outpt
Print #1, outpt
Next L
Close #1
End Sub
It is also assumed that the data starts in column A.
I struggled with that also numerous times, the only way I found was with a VBA function I created (the tricky part is determining the "widest" column for plain-text layout). Fair warning: I didn't build a lot "smarts" into this, the output can be a little quirky.
Usage:
Select the cells you want formatted to plain-text, then run the macro (I have the macro assigned to a button, I use it all the time!). If the top row is center-aligned, then let's /assume/ it's a header. And watch for right-aligned columns, and output those right-aligned.
The marco will copy the desired output to the clip-board, then paste the result in Notepad (or similar) to do with as desired.
Example output (I threw in some headers)
CustId Views Selected Cost
187712 201 37 0.18
2525 580 149 0.25
136829 137 43 0.31
The code:
Sub FormatSelectionToPlainText()
' ---------------------------------------------------------------------------
' Author: Jay R. Ohman
' Ohman Automation Corp., http://www.OhmanCorp.com
' ** disclaimer and release: I am NOT an expert **
' ** programmer, use my coding at your own risk! **
' ---------------------------------------------------------------------------
Dim rFound As Range, RngCol1 As Integer, RngRow1 As Integer, ActCol As Integer, ActRow As Integer, x As Integer
Dim MaxCellLen() As Variant, CellAlignRight() As Variant, HdrLen() As Variant, xDbg As Boolean, xVal As Variant
Dim SepSpace As Integer, RetStr As String, RetLen As Integer, MsgStr As String, HasHdr As Boolean
Dim GeneralIsRightAlignedFactor As Single, TotalRows As Integer
Dim oClip As DataObject
xDbg = True ' output stuff to the immediate window?
GeneralIsRightAlignedFactor = 0.75 ' threshhold for deeming a column as right-aligned
Set oClip = New DataObject
MsgStr = "(looking for top row to be center aligned as header)"
If MsgBox("Are the cells to be copied selected?" & vbCrLf & MsgStr, vbYesNo + vbQuestion, "Auto-Fill Time Slots") = vbYes Then
If (Selection Is Nothing) Then
MsgBox "Nothing Selected."
Else
SepSpace = 2 ' number of spaces between columns
RetLen = 0
HasHdr = True
Set rFound = Selection
RngCol1 = rFound.Column
RngRow1 = rFound.Row
Debug.Print Selection.Columns.Count
ReDim Preserve MaxCellLen(Selection.Columns.Count) ' max cell length
ReDim Preserve CellAlignRight(Selection.Columns.Count) ' track the cell alignment
ReDim Preserve HdrLen(Selection.Columns.Count) ' header row max cell length
For ActCol = RngCol1 To RngCol1 + Selection.Columns.Count - 1
x = (ActCol - RngCol1 + 1)
' If xDbg Then Debug.Print Cells(RngRow1, ActCol).HorizontalAlignment
If (Cells(RngRow1, ActCol).HorizontalAlignment <> xlCenter) And (Cells(RngRow1, ActCol).Value <> "") Then HasHdr = False
HdrLen(x) = IIf(HasHdr, Len(Cells(RngRow1, ActCol).Value), 0)
MaxCellLen(x) = 0
CellAlignRight(x) = 0
Next
If xDbg Then Debug.Print "HasHdr: " & HasHdr
TotalRows = (RngRow1 + Selection.Rows.Count) - (RngRow1 + IIf(HasHdr, 1, 0))
For ActCol = RngCol1 To RngCol1 + Selection.Columns.Count - 1 ' go find the longest text in each column
x = (ActCol - RngCol1 + 1)
xVal = IIf(HasHdr, 1, 0)
For ActRow = RngRow1 + xVal To RngRow1 + Selection.Rows.Count - 1
' If xDbg Then Debug.Print Cells(ActRow, ActCol).HorizontalAlignment
xVal = Cells(ActRow, ActCol).Value
If (MaxCellLen(x) < Len(Cells(ActRow, ActCol).Value)) Then MaxCellLen(x) = Len(xVal)
If (Cells(ActRow, ActCol).HorizontalAlignment = xlRight) Or _
((Cells(ActRow, ActCol).HorizontalAlignment = xlGeneral) And (IsDate(xVal) Or IsNumeric(xVal))) Then _
CellAlignRight(x) = CellAlignRight(x) + 1
Next
If xDbg Then Debug.Print "Max Length for Column " & ActCol & ": " & MaxCellLen(x) & _
", CellAlignRight.Count: " & CellAlignRight(x) & "/" & TotalRows
RetLen = RetLen + MaxCellLen(x) + SepSpace
Next
RetLen = RetLen - SepSpace ' subtract that last separator space
If HasHdr Then
For ActCol = RngCol1 To RngCol1 + Selection.Columns.Count - 1
x = (ActCol - RngCol1 + 1)
If (HdrLen(x) > MaxCellLen(x)) Then MaxCellLen(x) = HdrLen(x)
Next
End If
RetStr = "" ' build the output text
For ActRow = RngRow1 To RngRow1 + Selection.Rows.Count - 1
For ActCol = RngCol1 To RngCol1 + Selection.Columns.Count - 1
x = (ActCol - RngCol1 + 1)
MsgStr = Cells(ActRow, ActCol).Value ' re-use string variable
' format for right-aligned
If (CellAlignRight(x) / TotalRows >= GeneralIsRightAlignedFactor) And (Not (HasHdr And (ActRow = 1))) Or (Cells(ActRow, ActCol).HorizontalAlignment = xlRight) Then ' aligned right
RetStr = RetStr & Space(MaxCellLen(x) - Len(MsgStr)) & MsgStr
ElseIf (Cells(ActRow, ActCol).HorizontalAlignment = xlCenter) Then
xVal = Fix((MaxCellLen(x) - Len(MsgStr)) / 2)
RetStr = RetStr & Space(xVal) & MsgStr & Space(MaxCellLen(x) - Len(MsgStr) - xVal)
Else
RetStr = RetStr & MsgStr & Space(MaxCellLen(x) - Len(MsgStr))
End If
If ((ActCol - RngCol1) + 1 < UBound(MaxCellLen)) Then RetStr = RetStr & Space(SepSpace)
Next
RetStr = RetStr & vbCrLf
Next
oClip.SetText RetStr
oClip.PutInClipboard
MsgBox ("The selection has been copied to clipboard." & vbCrLf & "Max line length: " & RetLen)
End If
Else
MsgBox ("Have a nice day. :)")
End If
End Sub