通过缩进居中对齐选择中的最大数字
Center aligning largest number in selection by indenting
我长期以来一直对格式化感到沮丧。我经常手动执行此操作,但手动执行此操作需要很长时间,并且必须有一种方法可以使用 VBA 宏、条件格式或巧妙的数字格式来执行此操作。
下面是我想要的结果。它具有以下属性:
- 列中的最大数字(在本例中为列中的最后一个数字,$103,420)位于单元格的中央。
- 单元格中的最大数字不是居中对齐,而是右缩进直到值居中。
- 该列中的所有其他数字也向右缩进等量。这是可取的,因为它排列了每个数字中的个位、十位等。
- 负数用括号括起来。
- 美元符号与最左边的数字相邻。
- 大于 999 的数字正确包含逗号。
此结果是通过以下方式实现的:
- 应用以下数字格式:
$#,##0_);($#,##0)_);[=10=]_);@_)
- 手动调整最大数字单元格的右缩进以确定何时大致居中。如果更多 space 必须在一侧或另一侧,则较大的 space 留在数字的左侧。
我试图应用一种类似于用于响应 this question. 的数字格式
具体来说,我尝试使用它是使用以下数字格式将所有单元格居中对齐:$?,??0;($?,??0);
这会产生以下收盘价但不完全是下面的结果。
关于如何解决这个问题的想法?我在想象一个宏,它识别选择中的最大数字,获取该数字中的位数、字体大小、列的宽度,进行一些计算以产生所需的右缩进,然后应用右缩进。我只是不确定如何进行这种计算。
'Select your data range, and run formatCells_Accounting(). The number formatting in the selected cells will widen to the cell with the longest value. Note, the macro does not work on values greater than 10^14 (not sure why.)
Sub formatCells_Accounting()
Dim rg As Range
Set rg = Selection
maxVal = Application.WorksheetFunction.Max(rg)
minVal = Application.WorksheetFunction.Min(rg)
If Abs(minVal) > maxVal Then
longest_ = minVal
Else
longest_ = maxVal
End If
lenLongest = Len(CStr(Round(longest_, 0)))
rg.NumberFormat = "_($" & addCommasToFormat(lenLongest) & "_);" & _
"_(($" & addCommasToFormat(lenLongest) & ");" & _
"_($" & addCommasToFormat(lenLongest - 1) & "0_);" & _
"_(@_)"
End Sub
Function addCommasToFormat(ByVal lenLongest) As String
str_ = String(lenLongest, "?")
new_str_ = ""
For i = 1 To Len(str_)
If i Mod 3 = 1 And i <> 1 Then
new_str_ = new_str_ & ",?"
Else
new_str_ = new_str_ & "?"
End If
Next
addCommasToFormat = StrReverse(new_str_)
End Function
Chris - 你的回答没有达到我的期望(你的答案在美元符号和 "last" 数字之间留下 space 数字比集合中最长的数字短)
但是,您的代码是我提出的这个解决方案的有用起点。下图显示了结果以及此解决方案的固有缺点 - 运行在列中的数字以这种方式格式化后使用公式会导致奇怪的数字格式。
我能想出的唯一解决方案没有这个解决方案的问题是,一个依赖于估计缩进并应用它的解决方案。该解决方案仅在列宽未向前调整时才有效。如果调整宏,则必须重新运行。此外,由于缩进只能增加 1(不能少于 1),应用缩进的宏通常会导致列中的最大数字不完全居中。没什么大不了的,但是我当前的解决方案没有这些问题中的任何一个,并且在我的用例中,这些格式被用作格式化电子表格过程的最后一步,因此不太可能发生额外的计算,如果它们做,宏可以根据需要简单地重新运行。
'Select your data range, and run formatCells_Accounting(). The number formatting in the selected cells will widen to the cell with the longest value. Note, the macro does not work on values greater than 10^14 (not sure why.)
Sub formatCells_Accounting()
Dim rg, thisColRange, rCell As Range
Dim maxVal, minVal, valueLen, longest_, lenLongest As Long
Set rg = Selection
'Center aligns all selected cells
rg.HorizontalAlignment = xlCenter
'Loops through each column in the selected range so that each column can have it's own max value
For Each thisColRange In rg.Columns
maxVal = Application.WorksheetFunction.Max(thisColRange)
minVal = Application.WorksheetFunction.Min(thisColRange)
'The longest number in the range may be the most negative
'This if section accounts for this scenario
If Abs(minVal) > maxVal Then
longest_ = minVal
Else
longest_ = maxVal
End If
'Gets the length of the longest value rounded to the ones place (aka length not including decimals)
lenLongest = Len(CStr(Round(Abs(longest_), 0)))
'Creates a number format for every cell
For Each rCell In thisColRange.Cells
'Gets the length of the value in the current cell
valueLen = Len(CStr(Round(Abs(rCell.Value), 0)))
rCell.NumberFormat = "_(" & addCommasDollarsToFormat(lenLongest, valueLen, rCell.Value) & "_);" & _
"_(" & addCommasDollarsToFormat(lenLongest, valueLen, rCell.Value) & ")_);" & _
"_(" & Left(addCommasDollarsToFormat(lenLongest, 1, rCell.Value), Len(addCommasDollarsToFormat(lenLongest, 1, rCell.Value)) - 1) & "0_);" & _
"_(@_)"
Next
Next
End Sub
Function addCommasDollarsToFormat(ByVal lenLongest, ByVal valueLen, ByVal cellVal) As String
Dim new_str_ As String
Dim i, j As Long
'Initializes empty strings
new_str_ = ""
nearlyFinishedString = ""
'Adds ? and , through the length of the value currently being formatted
For i = 1 To valueLen
If i Mod 3 = 1 And i <> 1 Then
new_str_ = new_str_ & ",?"
Else
new_str_ = new_str_ & "?"
End If
Next
If cellVal < 0 Then
new_str_ = new_str_ & "$("
Else
new_str_ = new_str_ & "$"
End If
For j = i To lenLongest
If j Mod 3 = 1 Then
new_str_ = new_str_ & ",?"
Else
new_str_ = new_str_ & "?"
End If
Next
addCommasDollarsToFormat = StrReverse(new_str_)
End Function
解决方案可视化,下方显示解决方案的缺点。
我长期以来一直对格式化感到沮丧。我经常手动执行此操作,但手动执行此操作需要很长时间,并且必须有一种方法可以使用 VBA 宏、条件格式或巧妙的数字格式来执行此操作。
下面是我想要的结果。它具有以下属性:
- 列中的最大数字(在本例中为列中的最后一个数字,$103,420)位于单元格的中央。
- 单元格中的最大数字不是居中对齐,而是右缩进直到值居中。
- 该列中的所有其他数字也向右缩进等量。这是可取的,因为它排列了每个数字中的个位、十位等。
- 负数用括号括起来。
- 美元符号与最左边的数字相邻。
- 大于 999 的数字正确包含逗号。
此结果是通过以下方式实现的:
- 应用以下数字格式:
$#,##0_);($#,##0)_);[=10=]_);@_)
- 手动调整最大数字单元格的右缩进以确定何时大致居中。如果更多 space 必须在一侧或另一侧,则较大的 space 留在数字的左侧。
我试图应用一种类似于用于响应 this question. 的数字格式
具体来说,我尝试使用它是使用以下数字格式将所有单元格居中对齐:$?,??0;($?,??0);
这会产生以下收盘价但不完全是下面的结果。
关于如何解决这个问题的想法?我在想象一个宏,它识别选择中的最大数字,获取该数字中的位数、字体大小、列的宽度,进行一些计算以产生所需的右缩进,然后应用右缩进。我只是不确定如何进行这种计算。
'Select your data range, and run formatCells_Accounting(). The number formatting in the selected cells will widen to the cell with the longest value. Note, the macro does not work on values greater than 10^14 (not sure why.)
Sub formatCells_Accounting()
Dim rg As Range
Set rg = Selection
maxVal = Application.WorksheetFunction.Max(rg)
minVal = Application.WorksheetFunction.Min(rg)
If Abs(minVal) > maxVal Then
longest_ = minVal
Else
longest_ = maxVal
End If
lenLongest = Len(CStr(Round(longest_, 0)))
rg.NumberFormat = "_($" & addCommasToFormat(lenLongest) & "_);" & _
"_(($" & addCommasToFormat(lenLongest) & ");" & _
"_($" & addCommasToFormat(lenLongest - 1) & "0_);" & _
"_(@_)"
End Sub
Function addCommasToFormat(ByVal lenLongest) As String
str_ = String(lenLongest, "?")
new_str_ = ""
For i = 1 To Len(str_)
If i Mod 3 = 1 And i <> 1 Then
new_str_ = new_str_ & ",?"
Else
new_str_ = new_str_ & "?"
End If
Next
addCommasToFormat = StrReverse(new_str_)
End Function
Chris - 你的回答没有达到我的期望(你的答案在美元符号和 "last" 数字之间留下 space 数字比集合中最长的数字短)
但是,您的代码是我提出的这个解决方案的有用起点。下图显示了结果以及此解决方案的固有缺点 - 运行在列中的数字以这种方式格式化后使用公式会导致奇怪的数字格式。
我能想出的唯一解决方案没有这个解决方案的问题是,一个依赖于估计缩进并应用它的解决方案。该解决方案仅在列宽未向前调整时才有效。如果调整宏,则必须重新运行。此外,由于缩进只能增加 1(不能少于 1),应用缩进的宏通常会导致列中的最大数字不完全居中。没什么大不了的,但是我当前的解决方案没有这些问题中的任何一个,并且在我的用例中,这些格式被用作格式化电子表格过程的最后一步,因此不太可能发生额外的计算,如果它们做,宏可以根据需要简单地重新运行。
'Select your data range, and run formatCells_Accounting(). The number formatting in the selected cells will widen to the cell with the longest value. Note, the macro does not work on values greater than 10^14 (not sure why.)
Sub formatCells_Accounting()
Dim rg, thisColRange, rCell As Range
Dim maxVal, minVal, valueLen, longest_, lenLongest As Long
Set rg = Selection
'Center aligns all selected cells
rg.HorizontalAlignment = xlCenter
'Loops through each column in the selected range so that each column can have it's own max value
For Each thisColRange In rg.Columns
maxVal = Application.WorksheetFunction.Max(thisColRange)
minVal = Application.WorksheetFunction.Min(thisColRange)
'The longest number in the range may be the most negative
'This if section accounts for this scenario
If Abs(minVal) > maxVal Then
longest_ = minVal
Else
longest_ = maxVal
End If
'Gets the length of the longest value rounded to the ones place (aka length not including decimals)
lenLongest = Len(CStr(Round(Abs(longest_), 0)))
'Creates a number format for every cell
For Each rCell In thisColRange.Cells
'Gets the length of the value in the current cell
valueLen = Len(CStr(Round(Abs(rCell.Value), 0)))
rCell.NumberFormat = "_(" & addCommasDollarsToFormat(lenLongest, valueLen, rCell.Value) & "_);" & _
"_(" & addCommasDollarsToFormat(lenLongest, valueLen, rCell.Value) & ")_);" & _
"_(" & Left(addCommasDollarsToFormat(lenLongest, 1, rCell.Value), Len(addCommasDollarsToFormat(lenLongest, 1, rCell.Value)) - 1) & "0_);" & _
"_(@_)"
Next
Next
End Sub
Function addCommasDollarsToFormat(ByVal lenLongest, ByVal valueLen, ByVal cellVal) As String
Dim new_str_ As String
Dim i, j As Long
'Initializes empty strings
new_str_ = ""
nearlyFinishedString = ""
'Adds ? and , through the length of the value currently being formatted
For i = 1 To valueLen
If i Mod 3 = 1 And i <> 1 Then
new_str_ = new_str_ & ",?"
Else
new_str_ = new_str_ & "?"
End If
Next
If cellVal < 0 Then
new_str_ = new_str_ & "$("
Else
new_str_ = new_str_ & "$"
End If
For j = i To lenLongest
If j Mod 3 = 1 Then
new_str_ = new_str_ & ",?"
Else
new_str_ = new_str_ & "?"
End If
Next
addCommasDollarsToFormat = StrReverse(new_str_)
End Function
解决方案可视化,下方显示解决方案的缺点。