如何编写可以合并两列不确定长度的函数

时间:2019-05-10 00:55:37

标签: excel vba

我在excel中有一个表,该表有两列,分别称为标签和注释。

标签可以是空单元格,也可以是一个标签,也可以是多个标签,中间用逗号隔开。 (每个标签是一个字符串)

注释只是一个任意句子(注释)。

请注意,一个或多个标签不能反映特定的注释。

我想编写一个函数,该函数输出包含ID(第一行从0开始),注释以及与该注释关联的一个或多个标签的字符串。

如果我输入新的行/行,我的功能必须能够工作。

到目前为止,我认为我已经设法找到了可以读取表末尾的函数。现在,我需要能够将A列(标签)处理为特定格式,然后将处理后的列连接为类似于以下格式:

  

{“ id”:0,“ note”:“ colB的内容”,“标签”:[“ tag1”,“ tag2”等]}

这就是我所拥有的:(

Sub Parse()

ActiveWorkbook.Sheets.Add.Name = "Result"

idindex = 0

For Each Line In Sheets("Template").Range("B2:B" & 
Sheets("Template").Range("B2").End(xlDown).Row)

我不熟悉VBA,但是如果我能弄清楚如何处理列并附加ID,我想我就能弄清楚格式。

1 个答案:

答案 0 :(得分:1)

可能希望查看this,以获取有关如何在范围/列/工作表/等中找到“最后”行的良好信息。使用Option Explicit也是一个好习惯,它会强制您声明所有变量(有助于防止输入错误以及其他由隐式键入引起的难以跟踪的错误,等等)。

这是非常基本的字符串操作/字符串构建。您需要使用一些内置的VBA函数,例如JoinSplit等,并且需要转义引号,所以类似这样:

Sub Parse()
Dim thisCell As Range
Dim id As Long
Dim columnRange As Range
Dim note As String
Dim tags As String
Dim output As String
ActiveWorkbook.Sheets.Add.Name = "Result"

id = 0
With Sheets("Template")
    Set columnRange = .Range("B2:B" & .Range("B2").End(xlDown).Row)
    For Each thisCell In columnRange
        note = thisCell.Value
        tags = thisCell.Offset(0, -1).Value
        output = FormatOutput(id, note, tags)
        ' Remove the next line unless you want to print on the same worksheet in column C:
        thisCell.Offset(0, 1).Value = output
        ' This line prints to the Result sheet:
        Sheets("Result").Cells(id + 1, 1) = output
        id = id + 1
    Next
End With

End Sub

我做了这个奇特的功能来根据以下参数格式化输出:idthisNote(字符串)和theseTags(我们期望这是标记的逗号分隔字符串) 。我发现在编写脚本时像这样构建 parts 更容易,而不是试图跟踪我所有的引号以及它们是否正确转义/等等。

Function FormatOutput(id As Long, thisNote As String, theseTags As String) As String
    Const OPEN_ITEM As String = "{""id"":"
    Const OPEN_NOTE As String = " ""note"":"
    Const OPEN_TAGS As String = " ""tags"": ["
    Const CLOSE_ITEM As String = "]}"
    Const DBLQUOTE As String = """"
    Const COMMA As String = ","

    FormatOutput = OPEN_ITEM & CStr(id) & _
                OPEN_NOTE & DBLQUOTE & thisNote & DBLQUOTE & COMMA & _
                OPEN_TAGS & _
                    IIF(Len(Trim(theseTags)) = 0, "", _
                    DBLQUOTE & Join(Split(theseTags, COMMA), DBLQUOTE & COMMA & DBLQUOTE) & DBLQUOTE) & _
                CLOSE_ITEM
End Function

这给了我这样的输出:

  

{“ id”:0“ note”:“这是一个注释”,“标签”:[“ tag1”,“ tag3”,“ tag5”]}

它处理没有标签的笔记,反之亦然:

enter image description here


该功能(FormatOutput)是此操作背后的大脑。 (应该)应该非常简单,但是如果您不熟悉内置函数,则此部分会有些棘手:

DBLQUOTE & Join(Split(theseTags, COMMA), DBLQUOTE & COMMA & DBLQUOTE) & DBLQUOTE 

这确保我们将每个标记子字符串都用引号引起来,以用于输出。开头的DBLQUOTE在第一项之前放置一个",末尾的"则放在最后一个项目之后。

然后,我们(Split(theseTags, COMMA))在逗号上分割定界字符串,并Join在它们之间用新的定界符","返回。

我们需要做所有这些傻事,因为我们正在构建一个包含引号的字符串,否则该引号将被视为字符串的开头或结尾。