【问题标题】:VBA get length of string with white space characters like new line and carriage returnVBA获取带有空格字符(如换行符和回车符)的字符串长度
【发布时间】:2016-06-27 14:35:06
【问题描述】:

我正在尝试在 VBA 中将 Excel 列截断为特定长度。

但是LEN 函数似乎不会将\n and \r 视为单个字符。

有没有其他函数可以给出字符串的确切长度?

例如,我正在尝试获取单元格中以下字符串的长度。 (a\r\nb\r\nc\r\nd)

a
b
c
d

获取长度的代码。

print len( replace(replace(sheet1.Cells(1,1).value, chr(10), "-" ), chr(13), "#"))

输出:

7

字符串的实际长度为10

编辑

我终于明白了。它与空白字符无关,而是与其他一些特殊的 Unicode 字符有关。

VBA LEN 函数和 Java String.length() 方法不会给出字符串的大小,而是给出字符数。由于 Oracle 使用字节长度作为列的实际大小 (varchar(50) means 50 bytes),因此即使在截断之后也不允许插入字符串。

我最终使用以下代码在 Java 端截断字符串,因为我在 VBA 中找不到任何方法。

stringBytes = strCellValue.getBytes("UTF-8");
stringLength = stringBytes.length;

strCellValue = new String( stringBytes, 0, maxCellWidth, "UTF-8");
cell.setCellValue(strCellValue);

感谢 David Zemens 和 P57 提供的线索。

【问题讨论】:

  • 如果你知道你要剪断的长度,试试Application.Worksheetfunction.LEFT(string, # of chars you want to keep)
  • 它做同样的事情,它不考虑空白字符。我需要将 Excel 发送到 JDBC 将其放入 Oracle 表的服务器。使用了字符串的确切大小。
  • 您确定Len 没有为您计算这些字符吗?这对我来说是 2 Len(ChrW(10) & ChrW(13))
  • 我正在从notepad++ 复制文本,它会在选中时显示文本长度。 Notepad++ 也计算特殊字符。我还尝试通过使用 Javascript 打印来复制字符串。在记事本中,我可以用#% 替换\r\n,它给了我a#%b#%c#%d
  • 哇,复制粘贴到 Excel 中是非常重要的细节!您的回车符(字符代码 13)此时丢失,并且不再包含在单元格中的字符串值中。

标签: java vba excel


【解决方案1】:

我刚刚从 Notepad++ 测试了复制/粘贴,并验证它没有复制回车。

如果你检查你的单元格:

Instr(Sheet1.Cells(1,1).Value, vbCrLF)

您会看到0 的结果表明单元格中根本不存在vbCrLF (Char(10) & Char(13))。剪贴板必须以某种方式改变文本流。

所以字符串在Excel中的实际长度只有7。

要解决此问题,请将换行符转换为 vbCr & vbLf

Debug.Print Len(Replace(sheet1.Cells(1,1).value, vbLF, vbCR & vbLF))

注意:这可能不是一刀切的方法,它假定 所有 换行应该强制为回车 + 换行.您的里程可能会有所不同。

建议不要从 Notepad++ 复制/粘贴,而是直接将文本文件作为 TextStream 对象使用到您的 VBA...

【讨论】:

    【解决方案2】:

    我仍然很好奇,如果从 Java 读取 Excel 值,为什么您的示例会看到 10 个字符数。

    此代码进一步深入了解 Excel 范围如何复制回剪贴板。看起来在粘贴到单元格后,回车就永远消失了,而且,在复制之后,实际的剪贴板文本包括引号并附加了“\n\r”,但没有原始\r 字符的痕迹.

     Sub CellStringCheck()
    
        'Copy cell to clipboard
        Range("A1").Copy
    
        'Get clipboard contents directly
        Dim obj As MSForms.DataObject
        Set obj = New MSForms.DataObject
        obj.GetFromClipboard
    
        'Convert to string and set object to nothing
        Dim s As String
        s = obj.GetText
        Set obj = Nothing
    
        'Print Information
        Debug.Print "___________________"
        Debug.Print "String: "
        Debug.Print s
        Debug.Print "Len = " & Len(s)
        Debug.Print "Characters:"
        On Error Resume Next
        For i = 1 To Len(s)
            Debug.Print AscW(Mid(s, i, 1))
        Next
    
    End Sub
    

    如果我将A\n\rA 粘贴到范围 A1 中,此代码会生成以下内容:

        ___________________
    String:
    "A
    A "
    
    Len = 7
    Characters:
    34
    65
    10
    65
    34
    13
    10
    

    如果您将此剪贴板内容粘贴回 NP++,您会得到引号和所有内容,但 NP++ 会自动将单独的 \n 转换回 \n\r,显然是独立的,因为这不是剪贴板内容的一部分。

    我想知道这是否与剪贴板格式为 VbCFText 有关,但如果 VBA 处理剪贴板粘贴,则没有问题。如使用此代码所示,不会删除回车:

        Sub CellStringCheck()
    
        'Set clipboard contents
        Dim obj As MSForms.DataObject
        Set obj = New MSForms.DataObject
        obj.SetText vbLf & vbCr
        obj.PutInClipboard
    
        'Copy cell to clipboard
        obj.GetFromClipboard
        Range("A1") = obj.GetText
        Range("A1").Copy
    
        'Get clipboard contents directly
        obj.GetFromClipboard
    
        'Convert to string and set object to nothing
        Dim s As String
        s = obj.GetText
    
    
        'Print Information
        Debug.Print "___________________"
        Debug.Print obj.GetFormat(1)
        Debug.Print "String: "
        Debug.Print s
        Debug.Print "Len = " & Len(s)
        Debug.Print "Characters:"
        On Error Resume Next
        For i = 1 To Len(s)
            Debug.Print AscW(Mid(s, i, 1))
        Next
    
        Set obj = Nothing
    End Sub
    

    所以,说了这么多,我仍然不确定如果直接从 Java 读取单元格值,为什么你会发现回车,但是如果你正在浏览剪贴板,那么你可能会选择向上附加的回车。显然,Excel 和 NP++ 在粘贴时会进行自己的字符串处理。 Excel 删除回车,而 NP++ 将\n 转换为\n\r。如果您直接通过剪贴板,这不会发生,所以我怀疑它与应用程序级别的事件处理有关。我没有测试直接从 .Net 或 Java 读取或写入值,但我的猜测是直接访问值可以避免这个问题。另一种解决方法是对\n 的任何实例使用Environment.NewLine 或强制\n\r

    【讨论】:

    • 我也在研究这个,因为当我从 Excel 复制回记事本时,我再次得到回车字符。但是,为了安全起见,我决定将截断逻辑放在 Java 端。
    【解决方案3】:

    我怀疑这是最好的答案;事实上,我很确定,但一种相当复杂的方法是在使用 Len 函数之前,对回车符和新行进行替换。类似的东西

    for i = 1 to 10
        cells(i,1) = Replace(Cells(i,1), Char(10), "-") 'newline Chr(10)
        cells(i,1) = Replace(cells(i,1), Char(13), "-") 'carriage return Chr(13)
    next i
    

    然后,您将在换行符和回车符所在的位置出现破折号,并且可以将Len 应用于相关单元格以获得完整长度。

    【讨论】:

    • 我已经想到了,不幸的是第一行一次性替换了\n and \r
    • 好的。我以为你想把它们都换掉?
    • 我的意思是,\r\n 被视为单个字符。因此,如果它们连续出现,它们将被计为一个。
    • 我想你可以替换这个组合。 Replace(..., char(10) & char(13), "-")
    • @11thdimension 再一次,您的实际字符串处理是可疑的。 Replace(vbCrLf, Chr(10), "-") 非常清楚地为我提供了两个字符,保留回车并用破折号替换换行符......也许 Excel 的 Range 对象如何处理字符串或其变体形式
    【解决方案4】:

    你能举一个你的字符串的例子吗?

    Const vcr As String = "L" & vbCr & _
      "n" & vbCr & _
      "." & vbCr & _
      "."
    Const vlf As String = "L" & vbLf & _
      "n" & vbLf & _
      "." & vbLf & _
      "."
    Const vslashn As String = "l\nn\n.\n."
    
    len(vcr) gives 7
    len(vlf) gives 7
    
    Dim vslashnConverted As String    
    vslashnConverted = Replace(vslashn, "\n", crlf)
    
    Len(vslashn) : 10
    Len(vslashnConverted) : 4
    

    【讨论】:

      【解决方案5】:

      这是你想要的吗?

      Sub countStr()
         MsgBox (Len(Worksheets("sheet1").Cells(1, 1).Text))
      End Sub
      

      count text from cell

      【讨论】:

        【解决方案6】:

        使用此功能获得您想要的结果

        注意:认为 \r 和 \n 是两个不同的字符

        Public Function getlength(d As Range) As Long
            getlength = WorksheetFunction.Sum((Len(d) - Len(WorksheetFunction.Substitute(d, "\r", ""))) / 2, (Len(d) - Len(WorksheetFunction.Substitute(d, "\n", ""))) / 2, Len(WorksheetFunction.Substitute(WorksheetFunction.Substitute(d, "\r", ""), "\n", "")))
        End Function
        

        编辑 1:

        注意:以下函数将\r\n视为单个字符

        Public Function getlength(d As Range) As Long
            getlength = WorksheetFunction.Sum((Len(d) - Len(WorksheetFunction.Substitute(d, "\r\n", ""))) / 4, Len(WorksheetFunction.Substitute(d, "\r\n", "")))
        End Function
        

        【讨论】:

        • 这给了我相同的结果长度 7 对于我的示例 a\r\nb\r\nc\r\nd,实际的字符数应该是 10。
        猜你喜欢
        • 1970-01-01
        • 2010-09-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多