Attribute VB_Name = "CV"Option ExplicitFunction DrawTitle(theTitle As String)Selection.Style = ActiveDocument.Styles("Title")Selection.TypeText Text:=theTitleSelection.TypeParagraphEnd FunctionFunction DrawSubtitle(theSubtitle As String)Selection.Style = ActiveDocument.Styles("Heading 1")Selection.TypeText Text:=theSubtitleSelection.TypeParagraphEnd FunctionFunction DrawNormalText(theText As String)Selection.Style = ActiveDocument.Styles("Normal")Selection.TypeText Text:=theTextEnd FunctionFunction DrawSmallCaps(theSmallCaps As String)With Selection.Font.Bold = True.SmallCaps = TrueEnd WithSelection.TypeText Text:=theSmallCapsEnd FunctionFunction DrawTabEntry(theTabEntry As String)Selection.ParagraphFormat.TabStops.ClearAllActiveDocument.DefaultTabStop = InchesToPoints(0.5)Selection.ParagraphFormat.TabStops.Add Position:=InchesToPoints(6.5), _Alignment:=wdAlignTabRight, Leader:=wdTabLeaderSpacesSelection.TypeText Text:=vbTabSelection.Font.Bold = wdToggleWith Selection.Font.Bold = False.Italic = False.SmallCaps = False.Color = RGB(GREY_VALUE, GREY_VALUE, GREY_VALUE)End WithSelection.TypeText Text:=theTabEntrySelection.TypeParagraph' reset to normalSelection.Style = ActiveDocument.Styles("Normal")End FunctionFunction DrawBulletedList(theBulletEntries() As String)With ListGalleries(wdBulletGallery).ListTemplates(1).ListLevels(1).NumberFormat = ChrW(61623) ' Bullet character.NumberStyle = wdListNumberStyleBullet.NumberPosition = InchesToPoints(0.25).TextPosition = InchesToPoints(0.5).Font.Name = "Symbol"End With' Apply bullet list formatting to the selectionSelection.Range.ListFormat.ApplyListTemplateWithLevel _ListTemplate:=ListGalleries(wdBulletGallery).ListTemplates(1), _ContinuePreviousList:=False, _ApplyTo:=wdListApplyToWholeList, _DefaultListBehavior:=wdWord10ListBehavior' Insert each bullet entryDim bulletEntry As VariantFor Each bulletEntry In theBulletEntriesSelection.TypeText Text:=bulletEntrySelection.TypeParagraphNext bulletEntry' Remove bullet list formatting after the list is completeSelection.Range.ListFormat.RemoveNumbers NumberType:=wdNumberParagraphSelection.TypeParagraphEnd FunctionFunction DrawCompoundBulletedList(theTitles() As String, theDescriptions() As String)With ListGalleries(wdBulletGallery).ListTemplates(1).ListLevels(1).NumberFormat = ChrW(61623) ' Bullet character.NumberStyle = wdListNumberStyleBullet.NumberPosition = InchesToPoints(0.25).TextPosition = InchesToPoints(0.5).Font.Name = "Symbol"End With' Apply bullet list formatting to the selectionSelection.Range.ListFormat.ApplyListTemplateWithLevel _ListTemplate:=ListGalleries(wdBulletGallery).ListTemplates(1), _ContinuePreviousList:=False, _ApplyTo:=wdListApplyToWholeList, _DefaultListBehavior:=wdWord10ListBehaviorIf (UBound(theTitles) - LBound(theTitles)) <> (UBound(theTitles) - LBound(theTitles)) ThenMsgBox "Internal error in projects; this will result in an array bound error."End If' Insert each bullet entryDim i As IntegerFor i = LBound(theTitles) To UBound(theTitles)With Selection.Font.Bold = True.SmallCaps = TrueEnd WithSelection.TypeText Text:=theTitles(i)With Selection.Font.Bold = False.SmallCaps = FalseEnd WithSelection.TypeText Text:=" " & ChrW(8212) & " " & theDescriptions(i)Selection.TypeParagraphNext i' Remove bullet list formatting after the list is completeSelection.Range.ListFormat.RemoveNumbers NumberType:=wdNumberParagraphSelection.TypeParagraphEnd FunctionSub DrawCV()Attribute DrawCV.VB_ProcData.VB_Invoke_Func = "Normal.NewMacros.Macro1"Dim cvYAML As Object: Set cvYAML = New YAML' Q: Why is the business logic so terrible?' Why is every area of the dictionary referenced from the root with loads of ID_SELFs?' Why not assign it to variables to make it shorter?' A: Because VBA does not permit setting array length at runtime, and also seems' to crash with some sort of memory error when assigning subdictionaries to their' own variable.'' If I could go back to the drawing board, I probably would have drafted a better solution' (for example not using dictionaries and making the YAML class its own thing)' but at this stage of the project the perfect is the enemy of the good.cvYAML.path = YAML_PATHDim cvProps As Scripting.Dictionary: Set cvProps = cvYAML.props' read nameDrawTitle CStr(cvProps("name")(ID_SELF))' iterate through subheadings of "cv"Dim i As Integer: i = 0Dim j As Integer: j = 0For i = LBound(cvProps("cv")(ID_SELF)) To UBound(cvProps("cv")(ID_SELF))DrawSubtitle CStr(cvProps("cv")(ID_SELF)(i)("title")(ID_SELF))' iterate through entriesFor j = _LBound(cvProps("cv")(ID_SELF)(i)("entries")(ID_SELF)) To _UBound(cvProps("cv")(ID_SELF)(i)("entries")(ID_SELF))DrawSmallCaps CStr(cvProps("cv")(ID_SELF)(i)("entries")(ID_SELF)(j)("title")(ID_SELF))DrawTabEntry CStr(cvProps("cv")(ID_SELF)(i)("entries")(ID_SELF)(j)("date")(ID_SELF))If cvProps("cv")(ID_SELF)(i)("entries")(ID_SELF)(j).Exists("role") ThenDrawNormalText CStr(cvProps("cv")(ID_SELF)(i)("entries")(ID_SELF)(j)("role")(ID_SELF))If cvProps("cv")(ID_SELF)(i)("entries")(ID_SELF)(j).Exists("location") ThenDrawTabEntry CStr(cvProps("cv")(ID_SELF)(i)("entries")(ID_SELF)(j)("location")(ID_SELF))End IfEnd If' iterate through the bullets of the respective entryDim k As IntegerDim bulletedList() As StringReDim bulletedList(LBound(cvProps("cv")(ID_SELF)(i)("entries")(ID_SELF)(j)("bullets")(ID_SELF)) To _UBound(cvProps("cv")(ID_SELF)(i)("entries")(ID_SELF)(j)("bullets")(ID_SELF)))For k = LBound(cvProps("cv")(ID_SELF)(i)("entries")(ID_SELF)(j)("bullets")(ID_SELF)) To _UBound(cvProps("cv")(ID_SELF)(i)("entries")(ID_SELF)(j)("bullets")(ID_SELF))bulletedList(k) = CStr(cvProps("cv")(ID_SELF)(i)("entries")(ID_SELF)(j)("bullets")(ID_SELF)(k)(ID_SELF))Next kDrawBulletedList bulletedListNext jNext i' iterate through projectsDrawSubtitle "Projects"Dim l As IntegerDim titles() As StringDim descriptions() As StringReDim titles(LBound(cvProps("projects")(ID_SELF)) To UBound(cvProps("projects")(ID_SELF)))ReDim descriptions(LBound(cvProps("projects")(ID_SELF)) To UBound(cvProps("projects")(ID_SELF)))For l = LBound(cvProps("projects")(ID_SELF)) To UBound(cvProps("projects")(ID_SELF))' Debug.Print JsonConverter.ConvertToJson(cvProps("projects")(ID_SELF)(l), 2)titles(l) = CStr(cvProps("projects")(ID_SELF)(l)("title")(ID_SELF))descriptions(l) = CStr(cvProps("projects")(ID_SELF)(l)("description")(ID_SELF))Next lDrawCompoundBulletedList titles, descriptions' iterate through skillsEnd SubSub JsonTroubleshoot()Dim cvYAML As Object: Set cvYAML = New YAMLcvYAML.path = YAML_PATHDim cvProps As Scripting.Dictionary: Set cvProps = cvYAML.propsDrawNormalText JsonConverter.ConvertToJson(cvProps, 2)End Sub