【问题标题】:In Excel VBA creating a wordwrap function在 Excel VBA 中创建自动换行函数
【发布时间】:2013-09-12 16:07:56
【问题描述】:

通过大量研究,我找到了一个代码,可以将存储在单元格中的句子截断为 100 个字符或更少,并将多余的部分添加到第二个字符串中。我一直在努力尝试把它变成一个函数。

我想让函数接受一个范围(1 列,不同的行),或者,如果不可能的话,一个相同范围值的数组。另外应该有一种方法可以设置每个输出字符串可以容纳的字符数,输出为字符串数组。

即wordWrap(Input 'range or array', maxLength as integer) wordWrap 的输出将是一个结果数组

这是我当前的代码:

Sub wordWrap()
'This procedure is intended to check the character length of a string and truncate all the words over 100 characters
'To a second string.  (basically a word wrap)

Dim sumCount As Integer, newCount As Integer, i As Integer
Dim newString As String, newString2 As String
Dim words As Variant
Dim lenwords(0 To 1000) As Variant
Dim myRange As Range
sumCount = 0
newCount = 0
newString = ""
newString2 = ""
With Range("Q:Q")
    .NumberFormat = "@"
End With
Set myRange = Range("B3")
words = Split(myRange.Value, " ")
For i = 0 To UBound(words)
    lenwords(i) = Len(words(i))
    Range("Q3").Offset(i, 0) = CStr(words(i)) 'DEBUG
    Range("R3").Offset(i, 0) = lenwords(i) 'DEBUG
    If sumCount + (lenwords(i) + 1) < 100 Then
        sumCount = sumCount + (lenwords(i) + 1)
        newString = newString & " " & words(i)
    Else
        newCount = newCount + (lenwords(i) + 1)
        newString2 = newString2 & " " & words(i)
    End If
Next
'DEBUG
Range("S3") = CStr(newString)
Range("T3") = Trim(CStr(newString2))
Range("S4") = Len(newString)
Range("T4") = Len(newString2)
ActiveSheet.UsedRange.Columns.AutoFit
End Sub

因此,如果 ("B2:B6") 或等效数组 的范围最多输入 100 个字符:

c = wordWrap(Range("B2:B6"),100) 

基本上,这应该做的是计算每个单元格(或元素)的长度,并截断任何使字符串超过 100 个字符的额外单词,并将它们连接到输出数组中下一个元素的前面到下一个元素输出数组。如果这会使该元素超过 100 个字符,则再次执行相同的过程,直到所有元素包含少于 100 个字符长的句子字符串。它应该在末尾添加一个额外的元素以适应任何剩余的单词。

我一直在扯头发,试图让它发挥作用。我可以参考专家的建议。

任何帮助表示赞赏。

要求的示例:

http://s21.postimg.org/iywbgy307/trunc_ex.jpg

不过,输出应该是一个数组,而不是直接返回到工作表。

【问题讨论】:

  • 你能举个例子来证明你正在尝试什么吗?也许是截图?
  • 输出应该去哪里?

标签: arrays function vba excel


【解决方案1】:

功能:

Function WordWrap(ByVal Rng As Range, Optional ByVal MaxLength As Long = 100) As String()

    Dim rCell As Range
    Dim arrOutput() As String
    Dim sTemp As String
    Dim OutputIndex As Long
    Dim i As Long

    ReDim arrOutput(1 To Evaluate("CEILING(SUM(LEN(" & Rng.Address(External:=True) & "))," & MaxLength & ")/" & MaxLength) * 2)
    For Each rCell In Rng.Cells
        If Len(Trim(sTemp & " " & rCell.Text)) > MaxLength Then
            OutputIndex = OutputIndex + 1
            arrOutput(OutputIndex) = Trim(Left(sTemp & " " & rCell.Text, InStrRev(Left(sTemp & " " & rCell.Text, MaxLength), " ")))
            sTemp = Trim(Mid(sTemp & " " & rCell.Text, Len(arrOutput(OutputIndex)) + 2))
            For i = 1 To Len(sTemp) Step MaxLength
                If Len(sTemp) < MaxLength Then Exit For
                OutputIndex = OutputIndex + 1
                arrOutput(OutputIndex) = Trim(Left(sTemp, InStrRev(Left(sTemp, MaxLength), " ")))
                sTemp = Trim(Mid(sTemp, Len(arrOutput(OutputIndex)) + 2))
            Next i
        Else
            OutputIndex = OutputIndex + 1
            arrOutput(OutputIndex) = Trim(sTemp & " " & rCell.Text)
            sTemp = ""
        End If
    Next rCell
    OutputIndex = OutputIndex + 1
    arrOutput(OutputIndex) = sTemp

    ReDim Preserve arrOutput(1 To OutputIndex)
    WordWrap = arrOutput

    Erase arrOutput

End Function

电话:

Sub tgr()

    Dim arrWrapped() As String

    arrWrapped = WordWrap(Range("B2:B6"), 100)
    MsgBox Join(arrWrapped, Chr(10) & Chr(10))

End Sub

您可以将其输出到工作表中,而不是 msgbox,或者做任何您想做的事情。

【讨论】:

  • @chrisneilsen 我已经更新了整个单词的答案。
  • 现在效果很好。当克里斯尼尔森也击败我时,我只是在评论这个问题。我唯一需要改变的是函数名。显然 vba 不喜欢它被命名为 WordWrap。改成 WordsWrap 效果很好
  • 老虎,你是超人。但是该死的你给我这样的废话,这让我无法理解...... ;) Evaluate("CEILING(SUM(LEN(" &amp; Rng.Address(External:=True) &amp; "))," &amp; MaxLength &amp; ")/" &amp; MaxLength) * 2) Thanks Mate
  • 啊,对不起 :( 那行基本上说“将范围内每个单元格的长度相加,然后除以最大长度并向上取整,然后乘以 2”。这样做的原因是创建一个空数组来存储包装的单词。该数组不知道它最终会有多少行,所以它猜测,然后将猜测加倍以防万一。后来,数组被缩小到正确的大小使用ReDim Preserve
  • Rng.Address(External:=True) 是为了使函数可以在不同工作表(甚至不同工作簿)上的范围内运行,并且仍然可以正常工作。
【解决方案2】:

说你得到了一个字符串,并想要返回一个数组

这种方法可能会降低性能

dim words(1) as variant
dim lastSpace as Integer
dim i as Integer

words(1) = Cells(1, 1)

while(Len(words(UBound(words) - 1)) > 100) 'check if the newest array is > 100 characters
    Redim words(UBound(words) + 1)
    'find the last space
    for i = 0 to 100
        if(words(i) = " ") Then
            lastSpace = i
        EndIF
    Next
    words(UBound(words) - 1) = Mid(words(UBound(words) - 2), lastSpace) 'copy words after the last space before the 100th character
    words(UBound(words) - 2) = Left(words(UBound(words) - 2), 100 - lastSpace) 'copy the words from the beginning to the last space
Wend

不确定这是否会编译/运行,但它应该会给你一个大致的思路

【讨论】:

  • +1 教我如何嵌套 ubound。谢谢指点。
猜你喜欢
  • 1970-01-01
  • 2010-10-19
  • 1970-01-01
  • 2015-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多