Might want to see this for good info on how to find the "last" row in a range/column/sheet/etc. Also a good practice to use Option Explicit
which forces you to declare all variables (helps prevent typos, and other hard-to-trace errors that arise from implicit typing, etc.).
This is pretty basic string manipulation/string building. You'll need to use some of the built in VBA functions like Join
, Split
, etc., and you'll need to escape your quotation marks, so something like this:
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
I made this fancy function to format the output based on the paramaters: id
, thisNote
(string) and theseTags
(which we expect is the comma-delimited string of tags). I find it easier to build the parts like this when scripting, rather than trying to keep track of all my quotes and whether they're properly escaped/etc.:
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
And that gives me an output like:
{"id":0 "note":"this is a note", "tags": ["tag1","tag3","tag5"]}
It handles notes without tags and vice-versa:

That function (FormatOutput
) is the brains behind this operation. It should (hopefully) be pretty straightforward, but this part is a little tricky if you're unfamiliar with the built-ins:
DBLQUOTE & Join(Split(theseTags, COMMA), DBLQUOTE & COMMA & DBLQUOTE) & DBLQUOTE
This ensures that we wrap each of our tag substrings in quotation marks for the output. The DBLQUOTE
at the beginning puts a "
before the first item, and likewise at the end puts a "
after the last item.
Then we (Split(theseTags, COMMA)
) split the delimited string on the commas, and Join
them back with a new delimiter ","
between each.
We need to do all of this tomfoolery because we're building a string that contains quotation marks, which are otherwise treated as either the beginning or end of a string.