first commit

This commit is contained in:
2026-05-21 08:40:24 -04:00
commit b084545275
711 changed files with 3659856 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
# scripts/dataset/pyproject.toml
[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "section_1_word_library_module"
version = "0.1.0"
description = "Internal word doc generation library "
# MOVED: Configuration specific to setuptools goes here
[tool.setuptools]
packages = ["section_1_word_library_module"]

View File

@@ -0,0 +1,4 @@
Metadata-Version: 2.4
Name: section_1_word_library_module
Version: 0.1.0
Summary: Internal word doc generation library

View File

@@ -0,0 +1,11 @@
pyproject.toml
section_1_word_library_module/__init__.py
section_1_word_library_module/counselling_interval_analysis_word.py
section_1_word_library_module/naics_census_analysis.py
section_1_word_library_module/nbs_funding_analysis_word.py
section_1_word_library_module/satisfaction_survey_analysis_word.py
section_1_word_library_module/trainings_analysis_word.py
section_1_word_library_module.egg-info/PKG-INFO
section_1_word_library_module.egg-info/SOURCES.txt
section_1_word_library_module.egg-info/dependency_links.txt
section_1_word_library_module.egg-info/top_level.txt

View File

@@ -0,0 +1 @@
section_1_word_library_module

View File

@@ -0,0 +1,42 @@
from .trainings_analysis_word import (
training_events_page_one,
zero_attendee_events_page_maker,
attendee_bin_charts_page_maker,
primary_topic_analysis_page_maker,
attendee_counts_page_maker,
event_count_attendee_count_page_maker,
event_count_page_maker
)
from .counselling_interval_analysis_word import (
counselling_interval_analysis
)
from .nbs_funding_analysis_word import (
capital_acquisition_analysis_page,
new_business_start_analysis_page
)
from .naics_census_analysis import (
naics_penetration_page_one,
naics_penetration_page_two,
)
from .satisfaction_survey_analysis_word import (
client_survey_analysis_page_one
)
__all__ = [
'training_events_page_one',
'zero_attendee_events_page_maker',
'attendee_bin_charts_page_maker',
'primary_topic_analysis_page_maker',
'attendee_counts_page_maker',
'event_count_attendee_count_page_maker',
'event_count_page_maker',
'counselling_interval_analysis',
'capital_acquisition_analysis_page',
'new_business_start_analysis_page',
'naics_penetration_page_one',
'naics_penetration_page_two',
'client_survey_analysis_page_one'
]

View File

@@ -0,0 +1,65 @@
# FILE: counselling_interval_analysis_word.py
# CREATED: 1/12/25
# AUTHOR: Vincent Allen
# CONTACT: valle276@live.kutztown.edu vincent@vtallen.com
# PURPOSE:
# THis file contains the library code needed to generate word document pages for the Neoserra counseling interval scorecard
# Custom modules
from pasbdc_word_library import WordDocumentBuilder, PageConfig
# Third party modules
from docx import Document
from docx.shared import Pt, Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
def counselling_interval_analysis(
builder: WordDocumentBuilder,
days_client_signup_to_client_start:str,
days_client_signup_to_first_counseling:str,
days_client_start_to_first_counseling:str,
days_initial_to_followup_counseling:str,
days_training_to_counseling:str,
section_number: int = 2,
desk_review_section_number: int = 1,
**kwargs
):
heading_paragraph = builder.doc.add_heading(f"{desk_review_section_number}.{section_number} Counselling Interval Analysis", level=1)
heading_run = heading_paragraph.runs[0]
heading_run.font.rgb = RGBColor(113, 191, 68)
builder.doc.add_picture(days_client_signup_to_client_start, width=Inches(6), height=Inches(3.5))
heading_paragraph = builder.doc.add_paragraph()
heading_paragraph.add_run(f"\tFigure {desk_review_section_number}.{section_number}.{builder.figure_number}").bold = True
heading_paragraph.add_run(f" displays the average number of days between the client sign-up date and client start date.")
builder.figure_number += 1
builder.doc.add_picture(days_client_signup_to_first_counseling, width=Inches(6), height=Inches(3.5))
heading_paragraph = builder.doc.add_paragraph()
heading_paragraph.add_run(f"\tFigure {desk_review_section_number}.{section_number}.{builder.figure_number}").bold = True
heading_paragraph.add_run(f" displays the average number of days between client sign-up and first counseling session.")
builder.figure_number += 1
builder.doc.add_picture(days_client_start_to_first_counseling, width=Inches(6), height=Inches(3.5));
heading_paragraph = builder.doc.add_paragraph()
heading_paragraph.add_run(f"\tFigure {desk_review_section_number}.{section_number}.{builder.figure_number}").bold = True
heading_paragraph.add_run(" displays the average number of days between client start date to first counseling session.")
builder.figure_number += 1
builder.doc.add_picture(days_initial_to_followup_counseling, width=Inches(6), height=Inches(3.5))
heading_paragraph = builder.doc.add_paragraph()
heading_paragraph.add_run(f"\tFigure {desk_review_section_number}.{section_number}.{builder.figure_number}").bold = True
heading_paragraph.add_run(" displays the average number of days between initial counseling in the period to first followup counseling.")
builder.figure_number += 1
builder.doc.add_picture(days_training_to_counseling, width=Inches(6), height=Inches(3.5))
heading_paragraph = builder.doc.add_paragraph()
heading_paragraph.add_run(f"\tFigure {desk_review_section_number}.{section_number}.{builder.figure_number}").bold = True
heading_paragraph.add_run(" displays the average number of days between training in the period to first counseling session.")
builder.figure_number += 1

View File

@@ -0,0 +1,126 @@
# FILE: naics_census_analysis.py
# CREATED: 1/12/25
# AUTHOR: Vincent Allen
# CONTACT: valle276@live.kutztown.edu vincent@vtallen.com
# PURPOSE:
# Implements the library functions needed to display the naics census report within a word document. These are the functions only not the control code.
# Custom modules
from pasbdc_word_library import WordDocumentBuilder, PageConfig, theme_paragraph, theme_title
# Third party modules
from docx.shared import Pt, Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
def naics_penetration_page_one(
builder: WordDocumentBuilder,
sector_table: str,
penetration_graph: str,
section_number: int = 1,
desk_review_section_number: int = 1,
**kwargs
):
'''
parameters:
builder: WordDocumentBuilder - The document builder instance to use for generation
sector_table: str - Path to the image containing the NAICS sector description and census percentage table
penetration_graph: str - Path to the bar chart comparing PASBDC clients to census data by NAICS code
section_number: int - The report section number for this analysis
desk_review_section_number: int - The top-level desk review section number
**kwargs: dict - Additional keyword arguments for compatibility with PageConfig
returns:
None - Modifies the builder document in place
description:
Generates the first page of the NAICS Penetration Study. Configures page margins and
adds a styled section heading. Inserts a network-wide penetration graph followed
by a two-column table containing a sector reference image and a detailed data
source note explaining census coverage and USDA/BLS stand-ins.
'''
for section in builder.doc.sections:
section.top_margin = Inches(0.5)
section.bottom_margin = Inches(0.5)
section.left_margin = Inches(0.5)
section.right_margin = Inches(0.5)
heading_paragraph = builder.doc.add_paragraph()
heading_run = heading_paragraph.add_run(f"{desk_review_section_number}.{section_number} NAICS Penetration Study")
theme_title(heading_run)
builder.doc.add_picture(penetration_graph, width=Inches(7))
last_pg = builder.doc.paragraphs[-1]
last_pg.alignment = WD_ALIGN_PARAGRAPH.CENTER
last_pg.add_run(f"\nFigure {desk_review_section_number}.{section_number}.{builder.figure_number}").bold = True
last_pg.add_run(" shows the percentage of PASBDC clients per NAICS code compared to census percentages.")
dark_blue_color = RGBColor(15, 27, 38)
theme_paragraph(last_pg, 7, "Futera", dark_blue_color)
builder.figure_number += 1
picture_table = builder.doc.add_table(rows=2, cols=2)
row1_cells = picture_table.rows[0].cells
row2_cells = picture_table.rows[1].cells
sector_chart_paragrah = row1_cells[0].paragraphs[0]
sector_chart_run = sector_chart_paragrah.add_run()
sector_chart_run.add_picture(sector_table, width=Inches(2.5), height=Inches(3.5))
sector_chart_note_paragraph = row2_cells[0].paragraphs[0]
sector_chart_note_paragraph.add_run(f"Table {desk_review_section_number}.{section_number}.{builder.table_number}").bold = True
sector_chart_note_paragraph.add_run(" Shows the NAICS codes for each sector along with the percentage that sector makes up of the PA census data.")
theme_paragraph(sector_chart_note_paragraph, 7, "Futera", dark_blue_color)
builder.table_number += 1
county_chart_note_paragraph = row2_cells[1].paragraphs[0]
census_note_run = county_chart_note_paragraph.add_run(f"NOTE: The US census does not cover agriculture (as that is the responsibility of the USDA) nor government institutions (as the census measures the private sector). Agriculture data was sourced from the USDA where number of farm operations was used as the statistical stand in. As for government institutions, that data was sourced from the BLS by taking the number of NAICS code 92 organizations.")
census_note_run.font.name = 'Futera'
census_note_run.font.size = Pt(6)
census_note_run.font.color.rgb = dark_blue_color
def naics_penetration_page_two(
builder: WordDocumentBuilder,
county_map: str,
section_number: int = 1,
desk_review_section_number: int = 1,
**kwargs
):
'''
parameters:
builder: WordDocumentBuilder - The document builder instance to use for generation
county_map: str - Path to the heat map image showing missing NAICS codes by county
percent_missing_naics: float - The decimal percentage of missing NAICS codes network-wide (default: -99.99)
section_number: int - The report section number for this analysis
desk_review_section_number: int - The top-level desk review section number
**kwargs: dict - Additional keyword arguments for compatibility with PageConfig
returns:
None - Modifies the builder document in place
description:
Generates the second page of the NAICS Penetration Study focusing on data integrity.
Inserts a county-level heat map of missing NAICS codes and adds a descriptive
caption that dynamically reports the network-wide percentage of missing client
NAICS profiles.
'''
sector_chart_paragrah = builder.doc.add_paragraph()
sector_chart_run = sector_chart_paragrah.add_run()
sector_chart_run.add_picture(county_map, width=Inches(7))
last_pg = builder.doc.paragraphs[-1]
last_pg.alignment = WD_ALIGN_PARAGRAPH.CENTER
county_chart_note_paragraph = builder.doc.add_paragraph()
county_chart_note_paragraph.add_run(f"Figure {desk_review_section_number}.{section_number}.{builder.figure_number}").bold = True
county_chart_note_paragraph.add_run(" shows the percentage of clients whose NAICS codes were missing in Neoserra by county.")
dark_blue_color = RGBColor(15, 27, 38)
theme_paragraph(county_chart_note_paragraph, 7, "Futera", dark_blue_color)
builder.figure_number += 1

View File

@@ -0,0 +1,175 @@
# FILE: nbs_funding_analysis_word.py
# CREATED: 1/12/25
# AUTHOR: Vincent Allen
# CONTACT: valle276@live.kutztown.edu vincent@vtallen.com
# PURPOSE:
# Implements the word document generation functions needed to create the document for the nbs milestone analysis.
# Custom modules
from pasbdc_word_library import WordDocumentBuilder, PageConfig, theme_helpers, theme_paragraph, theme_title
# Third party modules
from docx.shared import Pt, Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
def capital_acquisition_analysis_page(
builder: WordDocumentBuilder,
funding_overview_graph: str,
funding_attribution_chart: str,
funding_attribution_potential_chart: str,
section_number: int = 5,
desk_review_section_number: int = 1,
**kwargs
):
'''
parameters:
builder: WordDocumentBuilder - The document builder instance to use for generation
funding_overview_graph: str - Path to the overview chart showing counts of milestones by documentation level
funding_attribution_chart: str - Path to the chart showing actual percentage of documented funding milestones
funding_attribution_potential_chart: str - Path to the chart showing potential attribution rates with proper documentation
funding_director_attribution: str - Path to the chart showing percentage of director-confirmed milestones
section_number: int - The report section number for this analysis
desk_review_section_number: int - The top-level desk review section number
**kwargs: dict - Additional keyword arguments for compatibility with PageConfig
returns:
None - Modifies the builder document in place
description:
Generates the Capital Funding Milestone Attribution Analysis page. Configures page margins
and adds a section title. Visualizes the documentation status of funding milestones
through a primary overview graph, a comparison grid for actual versus potential
attribution, and a final chart focused on director confirmations.
'''
for section in builder.doc.sections:
section.top_margin = Inches(0.5)
section.bottom_margin = Inches(0.5)
section.left_margin = Inches(0.5)
section.right_margin = Inches(0.5)
title_paragraph = builder.doc.add_paragraph()
title_run = title_paragraph.add_run(f"{desk_review_section_number}.{section_number} Capital Funding Milestone Attribution Analysis")
theme_title(title_run)
builder.doc.add_picture(funding_overview_graph, width=Inches(7))
last_pg = builder.doc.paragraphs[-1]
last_pg.alignment = WD_ALIGN_PARAGRAPH.CENTER
overview_chart_note_paragraph = builder.doc.add_paragraph()
overview_note_run = overview_chart_note_paragraph.add_run(f"Figure {desk_review_section_number}.{section_number}.{builder.figure_number}").bold = True
overview_chart_note_paragraph.add_run(" shows the counts of milestones in each documentation level per center.")
dark_blue_color = RGBColor(15, 27, 38)
theme_paragraph(overview_chart_note_paragraph, 9, "Futera", dark_blue_color)
builder.figure_number += 1
# Grid for Attribution Comparisons
picture_table = builder.doc.add_table(rows=2, cols=2)
row1_cells = picture_table.rows[0].cells
row2_cells = picture_table.rows[1].cells
# Actual Attribution
attr_chart_run = row1_cells[0].paragraphs[0].add_run()
attr_chart_run.add_picture(funding_attribution_chart, width=Inches(3.5))
attr_note_paragraph = row2_cells[0].paragraphs[0]
attr_note_paragraph.add_run(f"Figure {desk_review_section_number}.{section_number}.{builder.figure_number}").bold = True
attr_note_paragraph.add_run(" shows the percentage of funding attribution milestones had documentation per center.")
theme_paragraph(attr_note_paragraph, 9, "Futera", dark_blue_color)
theme_paragraph(attr_note_paragraph, 9, "Futera", dark_blue_color)
builder.figure_number += 1
# Potential Attribution
pot_chart_run = row1_cells[1].paragraphs[0].add_run()
pot_chart_run.add_picture(funding_attribution_potential_chart, width=Inches(3.5))
pot_note_paragraph = row2_cells[1].paragraphs[0]
pot_note_paragraph.add_run(f"Figure {desk_review_section_number}.{section_number}.{builder.figure_number}").bold = True
pot_note_paragraph.add_run(" shows what the attribution rate would be if all milestones were properly documented.")
theme_paragraph(pot_note_paragraph, 9, "Futera", dark_blue_color)
builder.figure_number += 1
def new_business_start_analysis_page(
builder: WordDocumentBuilder,
nbs_overview_graph: str,
nbs_attribution_chart: str,
nbs_attribution_potential_chart: str,
section_number: int = 5,
desk_review_section_number: int = 1,
**kwargs
):
'''
parameters:
builder: WordDocumentBuilder - The document builder instance to use for generation
nbs_overview_graph: str - Path to the overview chart showing NBS milestone counts by documentation level
nbs_attribution_chart: str - Path to the chart showing actual documented New Business Start (NBS) rates
nbs_attribution_potential_chart: str - Path to the chart showing potential NBS attribution if fully documented
nbs_director_attribution: str - Path to the chart showing director confirmation percentages for NBS milestones
section_number: int - The report section number for this analysis
desk_review_section_number: int - The top-level desk review section number
**kwargs: dict - Additional keyword arguments for compatibility with PageConfig
returns:
None - Modifies the builder document in place
description:
Constructs the New Business Start Milestone Attribution Analysis page. Sets up standard
margins and section headers before placing the NBS overview chart. Uses a structured
table to compare current attribution percentages with theoretical potential and
concludes with a network-wide analysis of director-confirmed start-up milestones.
'''
for section in builder.doc.sections:
section.top_margin = Inches(0.5)
section.bottom_margin = Inches(0.5)
section.left_margin = Inches(0.5)
section.right_margin = Inches(0.5)
title_paragraph = builder.doc.add_paragraph()
title_run = title_paragraph.add_run(f"{desk_review_section_number}.{section_number} New Business Start Milestone Attribution Analysis")
theme_title(title_run)
title_paragraph.alignment = WD_ALIGN_PARAGRAPH.LEFT
builder.doc.add_picture(nbs_overview_graph, width=Inches(7))
builder.doc.paragraphs[-1].alignment = WD_ALIGN_PARAGRAPH.CENTER
overview_note_paragraph = builder.doc.add_paragraph()
overview_note_paragraph.add_run(f"Figure {desk_review_section_number}.{section_number}.{builder.figure_number}").bold = True
overview_note_paragraph.add_run(" shows the counts of milestones in each documentation level per center.")
dark_blue_color = RGBColor(15, 27, 38)
theme_paragraph(overview_note_paragraph, 9, "Futera", dark_blue_color)
builder.figure_number += 1
picture_table = builder.doc.add_table(rows=2, cols=2)
row1_cells = picture_table.rows[0].cells
row2_cells = picture_table.rows[1].cells
# Actual NBS Attribution
attr_chart_run = row1_cells[0].paragraphs[0].add_run()
attr_chart_run.add_picture(nbs_attribution_chart, width=Inches(3.5))
attr_note_paragraph = row2_cells[0].paragraphs[0]
attr_note_paragraph.add_run(f"Figure {desk_review_section_number}.{section_number}.{builder.figure_number}").bold = True
attr_note_paragraph.add_run(" shows the percentage of NBS attribution milestones had documentation per center.")
theme_paragraph(attr_note_paragraph, 9, "Futera", dark_blue_color)
# Potential NBS Attribution
pot_chart_run = row1_cells[1].paragraphs[0].add_run()
pot_chart_run.add_picture(nbs_attribution_potential_chart, width=Inches(3.5))
pot_note_paragraph = row2_cells[1].paragraphs[0]
pot_note_paragraph.add_run(f"Figure {desk_review_section_number}.{section_number}.{builder.figure_number}").bold = True
pot_note_paragraph.add_run(" shows what the attribution rate would be if all milestones were properly documented.")
theme_paragraph(pot_note_paragraph, 9, "Futera", dark_blue_color)
builder.figure_number += 1

View File

@@ -0,0 +1,114 @@
# FILE: satisfaction_survey_analysis_word.py
# CREATED: 1/12/25
# AUTHOR: Vincent Allen
# CONTACT: valle276@live.kutztown.edu vincent@vtallen.com
# PURPOSE:
# Implements word document generation functions that can lay out the graphs for the Neoserra yearly satisfaction survey scorecard
# Custom modules
from pasbdc_word_library import WordDocumentBuilder, PageConfig, theme_title, theme_paragraph
# Third party modules
from docx.shared import Pt, Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
def client_survey_analysis_page_one(
builder: WordDocumentBuilder,
responses_count_chart: str,
recommendation_chart: str,
per_client_chart: str,
nps_chart: str,
section_number: int = 10,
desk_review_section_number: int = 1,
**kwargs
):
'''
parameters:
builder: WordDocumentBuilder - The document builder instance to use for generation
responses_count_chart: str - Path to the chart showing raw survey response counts per center
recommendation_chart: str - Path to the chart showing client recommendation scores
per_client_chart: str - Path to the chart showing survey responses normalized per client served
nps_chart: str - Path to the Net Promoter Score (NPS) visualization chart
section_number: int - The report section number for this analysis
desk_review_section_number: int - The top-level desk review section number
**kwargs: dict - Additional keyword arguments for compatibility with PageConfig
returns:
None - Modifies the builder document in place
description:
Constructs the Client Satisfaction Analysis page. Configures standard page margins
and generates a formatted layout containing a section header followed by two
organized tables. The tables display charts and figure labels for four key metrics:
raw response volume, responses per client served, client recommendation levels,
and calculated Net Promoter Scores (NPS).
'''
for section in builder.doc.sections:
section.top_margin = Inches(0.5)
section.bottom_margin = Inches(0.5)
section.left_margin = Inches(0.5)
section.right_margin = Inches(0.5)
heading_paragraph = builder.doc.add_paragraph()
heading_run = heading_paragraph.add_run(f"{desk_review_section_number}.{section_number} Client Satisfaction Analysis")
theme_title(heading_run)
# --- Overview Table (Response Counts) ---
overview_table = builder.doc.add_table(rows=2, cols=2)
row1_cells = overview_table.rows[0].cells
row2_cells = overview_table.rows[1].cells
# Response chart section
response_chart_paragrah = row1_cells[0].paragraphs[0]
response_chart_run = response_chart_paragrah.add_run()
response_chart_run.add_picture(responses_count_chart, width=Inches(4), height=Inches(2))
responses_count_note_paragraph = row2_cells[0].paragraphs[0]
note_run = responses_count_note_paragraph.add_run(f"Figure {desk_review_section_number}.{section_number}.{builder.figure_number}").bold = True
responses_count_note_paragraph.add_run(" shows the count of survey responses for clients per center.")
dark_blue_color = RGBColor(15, 27, 38)
theme_paragraph(responses_count_note_paragraph, 7, "Futera", dark_blue_color)
builder.figure_number += 1
# Response per client section
perclient_chart_paragrah = row1_cells[1].paragraphs[0]
perclient_chart_run = perclient_chart_paragrah.add_run()
perclient_chart_run.add_picture(per_client_chart, width=Inches(4), height=Inches(2))
perclient_note_paragraph = row2_cells[1].paragraphs[0]
perclient_note_paragraph.add_run(f"Figure {desk_review_section_number}.{section_number}.{builder.figure_number}").bold = True
perclient_note_paragraph.add_run(" shows the count of survey responses per client served per center.")
theme_paragraph(perclient_note_paragraph, 7, "Futera", dark_blue_color)
# Recommendation and NPS Table
q1_table = builder.doc.add_table(rows=2, cols=2)
row1_cells_q = q1_table.rows[0].cells
row2_cells_q = q1_table.rows[1].cells
# Recommendation chart section
rec_chart_paragrah = row1_cells_q[0].paragraphs[0]
rec_chart_run = rec_chart_paragrah.add_run()
rec_chart_run.add_picture(recommendation_chart, width=Inches(4), height=Inches(2))
rec_count_note_paragraph = row2_cells_q[0].paragraphs[0]
rec_count_note_paragraph.add_run(f"Figure {desk_review_section_number}.{section_number}.{builder.figure_number}").bold = True
rec_count_note_paragraph.add_run(" shows how clients responded to the listed question.")
theme_paragraph(rec_count_note_paragraph, 7, "Futera", dark_blue_color)
builder.figure_number += 1
# NPS section
nps_chart_paragrah = row1_cells_q[1].paragraphs[0]
nps_chart_run = nps_chart_paragrah.add_run()
nps_chart_run.add_picture(nps_chart, width=Inches(4), height=Inches(2))
nps_note_paragraph = row2_cells_q[1].paragraphs[0]
nps_note_paragraph.add_run(f"Figure {desk_review_section_number}.{section_number}.{builder.figure_number}").bold = True
nps_note_paragraph.add_run(" shows the NPS calculated for each center. See https://contentsquare.com/guides/net-promoter-score/ for a more in-depth explanation.")
theme_paragraph(nps_note_paragraph, 7, "Futera", dark_blue_color)
builder.figure_number += 1

View File

@@ -0,0 +1,861 @@
# FILE: trainings_analysis_word.py
# CREATED: 1/12/25
# AUTHOR: Vincent Allen
# CONTACT: valle276@live.kutztown.edu vincent@vtallen.com
# PURPOSE:
# Implements the library code for generating word documents for the trainings analysis. Each subsection in the report has its own funciton. The center specific
# training topic report has been extracted into a different file as this one is already VERY long.
# If you're looking for something to do this one could use some refactoring. The helper functions for each report can probably be consolidated in some manner.
# This was translated from a massive jupyter notebook and I did my best to compontetize things with the time constraints I had.
# Custom modules
from pasbdc_word_library import WordDocumentBuilder, PageConfig
#from ..word_generation_scripts.chart_filename_parsing import parse_and_organize_images
# Third party modules
from docx import Document
from docx.shared import Pt, Inches
from docx.enum.text import WD_ALIGN_PARAGRAPH
#python modules
import sys
def training_events_page_one(
builder:WordDocumentBuilder,
fiscal_year:str,
section_number:int=7,
desk_review_section_number:int=1,
**kwargs
):
'''
parameters:
builder: WordDocumentBuilder - The document builder instance to use for generation
fiscal_year: str - The fiscal year string (e.g., "FY25") for titles and text
section_number: int - The report section number for this analysis
desk_review_section_number: int - The top-level desk review section number
**kwargs: dict - Additional keyword arguments for compatibility with PageConfig
returns:
None - Modifies the builder document in place
description:
Initializes the Network Wide Training Event Analysis section. Configures page margins
and adds the section heading and introductory description to the Word document.
'''
# Saving the section number to hard code a section for this report
starting_section = builder.current_section
builder.current_section = section_number
for section in builder.doc.sections:
section.top_margin = Inches(0.5)
section.bottom_margin = Inches(0.5)
section.left_margin = Inches(0.5)
section.right_margin = Inches(0.5)
section_title = builder.doc.add_heading(f"{desk_review_section_number}.{section_number} Network Wide Training Event Analysis {fiscal_year}", level=1)
builder.doc.paragraphs[-1].alignment = WD_ALIGN_PARAGRAPH.CENTER
section_description = builder.doc.add_paragraph(
"\tThis section looks into both the quantity and type of training events that centers are providing to clients.\n"
f"Input data was exported from https://pasbdc.neoserra.com/coferences by filtering for all permitted centers and for {fiscal_year}\n\n"
"All graphs only display data for funding sources: Core Services, LEXNET, PDA, and NAP."
)
builder.current_section = starting_section
def zero_attendee_events_page_maker(
builder:WordDocumentBuilder,
fiscal_year:str,
total_trainings_count_chart:str,
total_trainings_percent_chart:str,
total_trainings_no_first_count_chart:str,
total_trainings_no_first_percent_chart:str,
total_trainings_no_first_no_pre_count_chart:str,
total_trainings_no_first_no_pre_percent_chart:str,
total_trainings_first_pre_only_count:str,
total_trainings_first_pre_only_percent:str,
total_trainings_ondemand_count:str,
total_trainings_ondemand_percent:str,
total_trainings_ondemand_no_first_count:str,
total_trainings_ondemand_no_first_percent:str,
total_trainings_ondemand_no_first_no_pre_count:str,
total_trainings_ondemand_no_first_no_pre_percent:str,
desk_review_section_number:int=1,
section_number:int=7,
**kwargs
):
'''
parameters:
builder: WordDocumentBuilder - The document builder instance to use for generation
fiscal_year: str - The fiscal year string for titles and figure labels
total_trainings_count_chart: str - Path to the total training counts bar chart
total_trainings_percent_chart: str - Path to the total training percentage bar chart
total_trainings_no_first_count_chart: str - Path to the count chart excluding First Steps
total_trainings_no_first_percent_chart: str - Path to the percentage chart excluding First Steps
total_trainings_no_first_no_pre_count_chart: str - Path to count chart excluding First Steps and Preplanning
total_trainings_no_first_no_pre_percent_chart: str - Path to percent chart excluding First Steps and Preplanning
total_trainings_first_pre_only_count: str - Path to count chart for First Steps and Preplanning only
total_trainings_first_pre_only_percent: str - Path to percent chart for First Steps and Preplanning only
total_trainings_ondemand_count: str - Path to count chart for On-Demand events
total_trainings_ondemand_percent: str - Path to percent chart for On-Demand events
total_trainings_ondemand_no_first_count: str - Path to On-Demand count chart excluding First Steps
total_trainings_ondemand_no_first_percent: str - Path to On-Demand percent chart excluding First Steps
total_trainings_ondemand_no_first_no_pre_count: str - Path to On-Demand count chart excluding First Steps/Preplanning
total_trainings_ondemand_no_first_no_pre_percent: str - Path to On-Demand percent chart excluding First Steps/Preplanning
desk_review_section_number: int - The top-level desk review section number
section_number: int - The report section number for this analysis
**kwargs: dict - Additional keyword arguments for compatibility with PageConfig
returns:
None - Modifies the builder document in place
description:
Constructs multiple pages in the report focusing on Training Event Counts.
Organizes bar charts into tables with corresponding figure labels, covering
general training events, filtered subsets, and specialized On-Demand training metrics.
'''
for section in builder.doc.sections:
section.top_margin = Inches(0.5)
section.bottom_margin = Inches(0.5)
section.left_margin = Inches(0.5)
section.right_margin = Inches(0.5)
old_section = builder.current_section
builder.current_section = section_number
builder.doc.add_heading("Zero Attendee Event Analysis", level=2)
picture_table = builder.doc.add_table(rows=4, cols=2)
row1_cells = picture_table.rows[0].cells
row2_cells = picture_table.rows[1].cells
row3_cells = picture_table.rows[2].cells
row4_cells = picture_table.rows[3].cells
# 1. Total count of trainings chart
total_chart_paragraph = row1_cells[0].paragraphs[0]
total_chart_run = total_chart_paragraph.add_run()
total_chart_run.add_picture(total_trainings_count_chart, width=Inches(4))
label_paragraph = row2_cells[0].paragraphs[0]
label_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
label_paragraph.add_run(" shows how many training events occurred at each center in the network.")
builder.figure_number += 1
# 2. Total count of trainings chart (Percent)
percent_chart_paragraph = row1_cells[1].paragraphs[0]
percent_chart_run = percent_chart_paragraph.add_run()
percent_chart_run.add_picture(total_trainings_percent_chart, width=Inches(4))
label_paragraph = row2_cells[1].paragraphs[0]
label_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
label_paragraph.add_run(" shows the percent of network wide events that had 0 attendees at each center.")
builder.figure_number += 1
# 3. Excluding first steps
nofirst_paragraph = row3_cells[0].paragraphs[0]
nofirst_chart_run = nofirst_paragraph.add_run()
nofirst_chart_run.add_picture(total_trainings_no_first_count_chart, width=Inches(4))
label_paragraph = row4_cells[0].paragraphs[0]
label_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
label_paragraph.add_run(" shows how many training events occurred at each center EXCLUDING 'First Steps' events (Those that had 'First Steps' or 'Next Steps' in the title of the training)")
builder.figure_number += 1
# 4. Excluding first steps (percent)
nofirst_paragraph = row3_cells[1].paragraphs[0]
nofirst_chart_run = nofirst_paragraph.add_run()
nofirst_chart_run.add_picture(total_trainings_no_first_percent_chart, width=Inches(4))
label_paragraph = row4_cells[1].paragraphs[0]
label_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
label_paragraph.add_run(" shows the percent of network wide events that had 0 attendees at each center (EXCLUDING First Steps).")
builder.figure_number += 1
# NEXT PAGE
builder.add_page_break()
# Make a new images table
picture_table = builder.doc.add_table(rows=4, cols=2)
row1_cells = picture_table.rows[0].cells
row2_cells = picture_table.rows[1].cells
# 5. Total trainings excluding first steps and preplanning
total_chart_paragraph = row1_cells[0].paragraphs[0]
total_chart_run = total_chart_paragraph.add_run()
total_chart_run.add_picture(total_trainings_no_first_no_pre_count_chart, width=Inches(4))
label_paragraph = row2_cells[0].paragraphs[0]
label_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
label_paragraph.add_run(" shows how many training events occurred at each center in the network EXCLUDING First Steps and 'Business Start-up/Preplanning' training events (Those that had 'Business Start-up/Preplanning' as their primary training topic).")
builder.figure_number += 1
# 6. Total trainings excluding first steps and preplanning (percent)
percent_chart_paragraph = row1_cells[1].paragraphs[0]
percent_chart_run = percent_chart_paragraph.add_run()
percent_chart_run.add_picture(total_trainings_no_first_no_pre_percent_chart, width=Inches(4))
label_paragraph = row2_cells[1].paragraphs[0]
label_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
label_paragraph.add_run(" shows the percent of network wide events that had 0 attendees at each center (EXCLUDING First Steps and Preplanning).")
builder.figure_number += 1
builder.doc.add_heading("Training Counts with Fist Steps and Business Start-up/Preplanning only", level=3)
# Make a new images table
picture_table = builder.doc.add_table(rows=4, cols=2)
row1_cells = picture_table.rows[0].cells
row2_cells = picture_table.rows[1].cells
# 5. Total trainings first steps and preplanning ONLY
total_chart_paragraph = row1_cells[0].paragraphs[0]
total_chart_run = total_chart_paragraph.add_run()
total_chart_run.add_picture(total_trainings_first_pre_only_count, width=Inches(4))
label_paragraph = row2_cells[0].paragraphs[0]
label_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
label_paragraph.add_run(" shows how many training events occurred at each center in the network including only First Steps and 'Business Start-up/Preplanning' training events")
builder.figure_number += 1
# 6. Total trainings first steps and preplanning ONLY (percent)
percent_chart_paragraph = row1_cells[1].paragraphs[0]
percent_chart_run = percent_chart_paragraph.add_run()
percent_chart_run.add_picture(total_trainings_first_pre_only_percent, width=Inches(4))
label_paragraph = row2_cells[1].paragraphs[0]
label_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
label_paragraph.add_run(" shows the percent of network wide events that had 0 attendees at each center (Including First Steps and Preplanning ONLY).")
builder.figure_number += 1
# NEW PAGE
builder.add_page_break()
# ON DEMAND SECTION
builder.doc.add_heading("On-Demand Training Events", level=3)
picture_table = builder.doc.add_table(rows=4, cols=2)
row1_cells = picture_table.rows[0].cells
row2_cells = picture_table.rows[1].cells
row3_cells = picture_table.rows[2].cells
row4_cells = picture_table.rows[3].cells
# 7. Total count of ONDEMAND trainings chart
total_chart_paragraph = row1_cells[0].paragraphs[0]
total_chart_run = total_chart_paragraph.add_run()
total_chart_run.add_picture(total_trainings_ondemand_count, width=Inches(4))
label_paragraph = row2_cells[0].paragraphs[0]
label_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
label_paragraph.add_run(" shows how many On-Demand training events occurred at each center in the network.")
builder.figure_number += 1
# 8. Total count of ONDEMAND trainings chart (Percent)
percent_chart_paragraph = row1_cells[1].paragraphs[0]
percent_chart_run = percent_chart_paragraph.add_run()
percent_chart_run.add_picture(total_trainings_ondemand_percent, width=Inches(4))
label_paragraph = row2_cells[1].paragraphs[0]
label_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
label_paragraph.add_run(" shows the percent of network wide on-demand events that had 0 attendees at each center.")
builder.figure_number += 1
# 9. Excluding first steps
nofirst_paragraph = row3_cells[0].paragraphs[0]
nofirst_chart_run = nofirst_paragraph.add_run()
nofirst_chart_run.add_picture(total_trainings_ondemand_no_first_count, width=Inches(4))
label_paragraph = row4_cells[0].paragraphs[0]
label_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
label_paragraph.add_run(" shows how many On-Demand training events occurred at each center (EXCLUDING First Steps events)")
builder.figure_number += 1
# 10. Excluding first steps (percent)
nofirst_paragraph = row3_cells[1].paragraphs[0]
nofirst_chart_run = nofirst_paragraph.add_run()
nofirst_chart_run.add_picture(total_trainings_ondemand_no_first_percent, width=Inches(4))
label_paragraph = row4_cells[1].paragraphs[0]
label_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
label_paragraph.add_run(" shows the percent of network wide on-demand events that had 0 attendees at each center (EXCLUDING First Steps)")
builder.figure_number += 1
# NEW PAGE
builder.add_page_break()
# Make a new images table
picture_table = builder.doc.add_table(rows=4, cols=2)
row1_cells = picture_table.rows[0].cells
row2_cells = picture_table.rows[1].cells
# 11. Total trainings excluding first steps and preplanning
total_chart_paragraph = row1_cells[0].paragraphs[0]
total_chart_run = total_chart_paragraph.add_run()
total_chart_run.add_picture(total_trainings_ondemand_no_first_no_pre_count, width=Inches(4))
label_paragraph = row2_cells[0].paragraphs[0]
label_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
label_paragraph.add_run(" shows how many On-Demand training events occurred at each center in the network EXCLUDING First Steps and 'Business Start-up/Preplanning' training events (Those that had 'Business Start-up/Preplanning' as their primary training topic).")
builder.figure_number += 1
# 12. Total trainings excluding first steps and preplanning (percent)
percent_chart_paragraph = row1_cells[1].paragraphs[0]
percent_chart_run = percent_chart_paragraph.add_run()
percent_chart_run.add_picture(total_trainings_ondemand_no_first_no_pre_percent, width=Inches(4))
label_paragraph = row2_cells[1].paragraphs[0]
label_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
label_paragraph.add_run(" shows the percent of network wide on-demand events that had 0 attendees at each center (EXCLUDING First Steps and Preplanning)")
builder.figure_number += 1
builder.current_section = old_section
def attendee_bin_charts_page_maker(
builder:WordDocumentBuilder,
center:str,
attendee_bin_chart_total_count:str,
attendee_bin_chart_total_percent:str,
attendee_bin_chart_no_first_no_pre_total_count:str,
attendee_bin_chart_no_first_no_pre_total_percent:str,
attendee_bin_chart_first_pre_total_count:str,
attendee_bin_chart_first_pre_total_percent:str,
section_number:int=7,
desk_review_section_number:int=1,
**kwargs
):
'''
parameters:
builder: WordDocumentBuilder - The document builder instance to use for generation
center: str - The center that these graphs belong to, set to network wide for all centers
attendee_bin_chart_total_count: str - Path to the total count stacked bar chart for attendee ranges
attendee_bin_chart_total_percent: str - Path to the total percentage stacked bar chart for attendee ranges
attendee_bin_chart_no_first_total_count: str - Path to count chart excluding First Steps
attendee_bin_chart_no_first_total_percent: str - Path to percentage chart excluding First Steps
attendee_bin_chart_no_first_no_pre_total_count: str - Path to count chart excluding First Steps and Preplanning
attendee_bin_chart_no_first_no_pre_total_percent: str - Path to percent chart excluding First Steps and Preplanning
attendee_bin_chart_first_pre_total_count: str - Path to count chart for First Steps and Preplanning only
attendee_bin_chart_first_pre_total_percent: str - Path to percent chart for First Steps and Preplanning only
section_number: int - The report section number for this analysis
desk_review_section_number: int - The top-level desk review section number
**kwargs: dict - Additional keyword arguments for compatibility with PageConfig
returns:
None - Modifies the builder document in place
description:
Creates report pages visualizing training event distribution by attendee count ranges
(e.g., 1-5, 6-14). Uses tables to display side-by-side count and percentage charts
for various filtered data subsets.
'''
for section in builder.doc.sections:
section.top_margin = Inches(0.5)
section.bottom_margin = Inches(0.5)
section.left_margin = Inches(0.5)
section.right_margin = Inches(0.5)
old_section = builder.current_section
builder.current_section = section_number
builder.doc.add_heading(f"{center} Grouped Attendee Count Analysis", level=2)
picture_table = builder.doc.add_table(rows=4, cols=2)
row1_cells = picture_table.rows[0].cells
row2_cells = picture_table.rows[1].cells
row3_cells = picture_table.rows[2].cells
row4_cells = picture_table.rows[3].cells
# 1. All events
total_chart_paragrah = row1_cells[0].paragraphs[0]
total_chart_run = total_chart_paragrah.add_run()
total_chart_run.add_picture(attendee_bin_chart_total_count, width=Inches(4))
label_paragraph = row2_cells[0].paragraphs[0]
label_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
label_paragraph.add_run(" shows the number of training events that fell into each attendee range category.")
builder.figure_number += 1
# 2. All events (Percent)
percent_chart_paragraph = row1_cells[1].paragraphs[0]
percent_chart_run = percent_chart_paragraph.add_run()
percent_chart_run.add_picture(attendee_bin_chart_total_percent, width=Inches(4))
label_paragraph = row2_cells[1].paragraphs[0]
label_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold=True
label_paragraph.add_run(" shows the percentage of training events that fell into each attendee range category.")
builder.figure_number += 1
# 5. Excluding first steps and pre planning
total_chart_paragrah = row3_cells[0].paragraphs[0]
total_chart_run = total_chart_paragrah.add_run()
total_chart_run.add_picture(attendee_bin_chart_no_first_no_pre_total_count, width=Inches(3.5))
label_paragraph = row4_cells[0].paragraphs[0]
label_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
label_paragraph.add_run(" shows the number of training events, EXCLUDING First Steps and Pre-planning, that fell into each attendee range category.")
builder.figure_number += 1
# 6. Excluding first steps and pre planning (percent)
percent_chart_paragraph = row3_cells[1].paragraphs[0]
percent_chart_run = percent_chart_paragraph.add_run()
percent_chart_run.add_picture(attendee_bin_chart_no_first_no_pre_total_percent, width=Inches(3.5))
label_paragraph = row4_cells[1].paragraphs[0]
label_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold=True
label_paragraph.add_run(" shows the percentage of training events, EXCLUDING First Steps and Pre-planning, that fell into each attendee range category.")
builder.figure_number += 1
# NEW PAGE
picture_table = builder.doc.add_table(rows=4, cols=2)
row1_cells = picture_table.rows[0].cells
row2_cells = picture_table.rows[1].cells
# 7. First steps and pre planning only
nofirst_paragraph = row1_cells[0].paragraphs[0]
nofirst_chart_run = nofirst_paragraph.add_run()
nofirst_chart_run.add_picture(attendee_bin_chart_first_pre_total_count, width=Inches(3.5))
label_paragraph = row2_cells[0].paragraphs[0]
label_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
label_paragraph.add_run(" shows the number of training events, that were First Steps or Pre-planning, that fell into each attendee range category.")
builder.figure_number += 1
# 8. First steps and pre planning only (percent)
nofirst_paragraph = row1_cells[1].paragraphs[0]
nofirst_chart_run = nofirst_paragraph.add_run()
nofirst_chart_run.add_picture(attendee_bin_chart_first_pre_total_percent, width=Inches(3.5))
label_paragraph = row2_cells[1].paragraphs[0]
label_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
label_paragraph.add_run(" shows the percentage of training events, that were First Steps or Pre-planning, that fell into each attendee range category.")
builder.figure_number += 1
builder.current_section = old_section
def primary_topic_analysis_page_maker(
builder:WordDocumentBuilder,
center:str,
primary_topic_pie_total:str,
primary_topic_pie_no_first_total:str,
primary_topic_bar_small_topics_total:str,
primary_topic_bar_small_topics_percent:str,
section_number:int=7,
desk_review_section_number:int=1,
is_center_specific:bool = False,
**kwargs
):
'''
parameters:
builder: WordDocumentBuilder - The document builder instance to use for generation
center: str - The center that these graphs belong to, set to network wide for all centers
primary_topic_pie_total: str - Path to the network-wide topic distribution pie chart
primary_topic_pie_no_first_total: str - Path to topic distribution pie chart excluding First Steps
primary_topic_bar_total: str - Path to the primary topic count bar chart
primary_topic_bar_percent: str - Path to the primary topic percentage bar chart
primary_topic_bar_no_first_total: str - Path to topic count bar chart excluding First Steps
primary_topic_bar_no_first_percent: str - Path to topic percent bar chart excluding First Steps
primary_topic_bar_five_fewer_total: str - Path to count chart for low-frequency topics (<= 5 events)
primary_topic_bar_five_fewer_percent: str - Path to percent chart for low-frequency topics (<= 5 events)
section_number: int - The report section number for this analysis
desk_review_section_number: int - The top-level desk review section number
is_center_specific: bool - Whether or not this report is being used for a network wide report or a center specific one. This changes how the figure descriptions are worded
**kwargs: dict - Additional keyword arguments for compatibility with PageConfig
returns:
None - Modifies the builder document in place
description:
Generates analysis pages for Primary Training Topics. Includes pie charts
representing overall network distribution and bar charts for specific counts,
percentage breakdowns, and a detailed look at niche topics with low event volume.
'''
for section in builder.doc.sections:
section.top_margin = Inches(0.5)
section.bottom_margin = Inches(0.5)
section.left_margin = Inches(0.5)
section.right_margin = Inches(0.5)
old_section = builder.current_section
builder.current_section = section_number
builder.doc.add_heading(f"{center} Primary Training Topic Analysis", level=2)
# Updated to 6 rows to accommodate 6 graphs (Image row followed by Label row for each pair)
picture_table = builder.doc.add_table(rows=6, cols=2)
row1_cells = picture_table.rows[0].cells
row2_cells = picture_table.rows[1].cells
# 1. Total distribution pie
total_pie_paragraph = row1_cells[0].paragraphs[0]
total_pie_run = total_pie_paragraph.add_run()
total_pie_run.add_picture(primary_topic_pie_total, width=Inches(3.5))
label_paragraph = row2_cells[0].paragraphs[0]
label_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
label_paragraph.add_run(f" shows the distribution of primary training topics {"for this center." if is_center_specific else "across the entire network."}")
builder.figure_number += 1
# 2. No first steps distribution pie
nofirst_pie_paragraph = row1_cells[1].paragraphs[0]
nofirst_pie_run = nofirst_pie_paragraph.add_run()
nofirst_pie_run.add_picture(primary_topic_pie_no_first_total, width=Inches(3.5))
label_paragraph = row2_cells[1].paragraphs[0]
label_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
label_paragraph.add_run(f" shows the distribution of primary training topics {"for this center" if is_center_specific else "across the entire network"}, EXCLUDING 'First Steps'.")
builder.figure_number += 1
builder.doc.add_heading("Topics With 2% or Fewer Associated Training Events", level=3)
# Make a new images table for the remaining 2 graphs
picture_table = builder.doc.add_table(rows=2, cols=2)
row1_cells = picture_table.rows[0].cells
row2_cells = picture_table.rows[1].cells
# 7. Small topics count
fewer_count_paragraph = row1_cells[0].paragraphs[0]
fewer_count_run = fewer_count_paragraph.add_run()
fewer_count_run.add_picture(primary_topic_bar_small_topics_total, width=Inches(3.5))
label_paragraph = row2_cells[0].paragraphs[0]
label_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
label_paragraph.add_run(" shows the percentage of training events for primary training topics that occurred at a rate less than 2%.")
builder.figure_number += 1
# 8. Five or fewer trainings (percent)
fewer_percent_paragraph = row1_cells[1].paragraphs[0]
fewer_percent_run = fewer_percent_paragraph.add_run()
fewer_percent_run.add_picture(primary_topic_bar_small_topics_percent, width=Inches(3.5))
label_paragraph = row2_cells[1].paragraphs[0]
label_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold=True
label_paragraph.add_run(" shows the count of primary training topics that occurred at a rate less than 2% within the data.")
builder.figure_number += 1
builder.current_section = old_section
def attendee_counts_page_maker(
builder: WordDocumentBuilder,
attendee_counts_total:str,
attendee_counts_percent:str,
attendee_counts_first_pre_count:str,
attendee_counts_first_pre_percent:str,
section_number:int=7,
desk_review_section_number:int=1,
**kwargs
):
'''
parameters:
builder: WordDocumentBuilder - The document builder instance to use for generation
attendee_counts_total: str - Path to the total attendee sum bar chart per center
attendee_counts_percent: str - Path to the percentage of total attendees bar chart
attendee_counts_no_first_total: str - Path to attendee count chart excluding First Steps
attendee_counts_no_first_percent: str - Path to attendee percent chart excluding First Steps
attendee_counts_no_first_no_pre_total: str - Path to attendee count chart excluding First Steps/Preplanning
attendee_counts_no_first_no_pre_percent: str - Path to attendee percent chart excluding First Steps/Preplanning
attendee_counts_first_pre_count: str - Path to attendee count chart for First Steps and Preplanning only
attendee_counts_first_pre_percent: str - Path to attendee percent chart for First Steps and Preplanning only
section_number: int - The report section number for this analysis
desk_review_section_number: int - The top-level desk review section number
**kwargs: dict - Additional keyword arguments for compatibility with PageConfig
returns:
None - Modifies the builder document in place
description:
Constructs report pages analyzing the total number of attendees served by each
center. Compares raw attendee sums and network percentages across multiple
filters including First Steps and Business Preplanning exclusions.
'''
old_section = builder.current_section
builder.current_section = section_number
builder.doc.add_heading("Training Event Attendee Counts Per Center", level=2)
picture_table = builder.doc.add_table(rows=6, cols=2)
row1_cells = picture_table.rows[0].cells
row2_cells = picture_table.rows[1].cells
row3_cells = picture_table.rows[2].cells
row4_cells = picture_table.rows[3].cells
row5_cells = picture_table.rows[4].cells
row6_cells = picture_table.rows[5].cells
# 1. Total count of attendees chart
total_chart_paragrah = row1_cells[0].paragraphs[0]
total_chart_run = total_chart_paragrah.add_run()
total_chart_run.add_picture(attendee_counts_total, width=Inches(3.5))
label_paragraph = row2_cells[0].paragraphs[0]
label_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
label_paragraph.add_run(" shows the total number of attendees for training events at each center in the network.")
builder.figure_number += 1
# 2. Total count of attendees chart (Percent)
percent_chart_paragraph = row1_cells[1].paragraphs[0]
percent_chart_run = percent_chart_paragraph.add_run()
percent_chart_run.add_picture(attendee_counts_percent, width=Inches(3.5))
label_paragraph = row2_cells[1].paragraphs[0]
label_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
label_paragraph.add_run(" shows the percent of total attendees for trainings in the filter used to create the graph, that happened at each center.")
builder.figure_number += 1
# 7. First steps and preplanning ONLY
only_count_paragraph = row3_cells[0].paragraphs[0]
only_count_run = only_count_paragraph.add_run()
only_count_run.add_picture(attendee_counts_first_pre_count, width=Inches(3.5))
label_paragraph = row4_cells[0].paragraphs[0]
label_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
label_paragraph.add_run(" shows the total number of training event attendees at each center in the network including only First Steps and 'Business Start-up/Preplanning' training events")
builder.figure_number += 1
# 8. First steps and preplanning ONLY (percent)
only_percent_paragraph = row3_cells[1].paragraphs[0]
only_percent_run = only_percent_paragraph.add_run()
only_percent_run.add_picture(attendee_counts_first_pre_percent, width=Inches(3.5))
label_paragraph = row4_cells[1].paragraphs[0]
label_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
label_paragraph.add_run(" shows the percent of all training event attendees in the filter (including first steps and Preplanning ONLY) used to create the graph, that happened at each center.")
builder.figure_number += 1
builder.current_section = old_section
def event_count_attendee_count_page_maker(
builder:WordDocumentBuilder,
event_count_attendee_count_total:str,
event_count_attendee_count_first_pre_total:str,
section_number:int=7,
desk_review_section_number:int=1,
**kwargs
):
'''
parameters:
builder: WordDocumentBuilder - The document builder instance to use for generation
event_count_attendee_count_total: str - Path to the total event/attendee comparison chart
event_count_attendee_count_no_first_total: str - Path to comparison chart excluding First Steps
event_count_attendee_count_no_first_no_pre_total: str - Path to comparison chart excluding First Steps/Preplanning
event_count_attendee_count_first_pre_total: str - Path to comparison chart for First Steps/Preplanning only
**kwargs: dict - Additional keyword arguments for compatibility with PageConfig
returns:
None - Modifies the builder document in place
description:
Adds a section comparing event counts and attendee distributions. Unlike other
page makers, this function places large, full-width images sequentially without
using tables to provide a detailed comparison of center performance.
'''
old_section = builder.current_section
builder.current_section = section_number
builder.doc.add_heading("Comparison of Event Counts and Attendee Counts", level=2)
# Total event and attendee count
builder.doc.add_picture(event_count_attendee_count_total, width=Inches(6))
label_paragraph = builder.doc.add_paragraph()
label_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
label_paragraph.add_run(" shows how many training events occurred at each center in the network.")
builder.figure_number += 1
# First steps and preplanning only
builder.doc.add_picture(event_count_attendee_count_first_pre_total, width=Inches(6))
label_paragraph = builder.doc.add_paragraph()
label_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
label_paragraph.add_run(" shows how many training events occurred at each center in the network including only First Steps and 'Business Start-up/Preplanning' training events")
builder.figure_number += 1
builder.current_section = old_section
def event_count_page_maker(
builder: WordDocumentBuilder,
event_counts_total: str,
event_counts_percent: str,
event_counts_attended_total: str,
event_counts_attended_percent: str,
event_counts_no_first_total: str,
event_counts_no_first_percent: str,
event_counts_no_first_attended_total: str,
event_counts_no_first_attended_percent: str,
event_counts_no_first_no_pre_total: str,
event_counts_no_first_no_pre_percent: str,
event_counts_first_only:str,
event_counts_first_only_percent:str,
event_counts_first_pre_only:str,
event_counts_first_pre_only_percent:str,
section_number: int = 7,
desk_review_section_number: int = 1,
**kwargs
):
'''
parameters:
builder: WordDocumentBuilder - The document builder instance to use for generation
event_counts_total: str - Path to total event counts chart
event_counts_percent: str - Path to total event percentage chart
event_counts_attended_total: str - Path to counts for events with > 0 attendees
event_counts_attended_percent: str - Path to percentage for events with > 0 attendees
event_counts_no_first_total: str - Path to counts excluding First Steps
event_counts_no_first_percent: str - Path to percentage excluding First Steps
event_counts_no_first_attended_total: str - Path to counts for attended events excluding First Steps
event_counts_no_first_attended_percent: str - Path to percentage for attended events excluding First Steps
event_counts_no_first_no_pre_total: str - Path to counts excluding First Steps and Pre-planning
event_counts_no_first_no_pre_percent: str - Path to percentage excluding First Steps and Pre-planning
section_number: int - The report section number
desk_review_section_number: int - The top-level section number
**kwargs: dict - Compatibility for PageConfig
returns:
None - Modifies the builder document in place
'''
for section in builder.doc.sections:
section.top_margin = Inches(0.5)
section.bottom_margin = Inches(0.5)
section.left_margin = Inches(0.5)
section.right_margin = Inches(0.5)
old_section = builder.current_section
builder.current_section = section_number
builder.doc.add_heading("Training Event Count Analysis", level=2)
# PAGE 1: Total, Attended, and No First Steps
picture_table = builder.doc.add_table(rows=6, cols=2)
rows = picture_table.rows
# 1. All Events
rows[0].cells[0].paragraphs[0].add_run().add_picture(event_counts_total, width=Inches(3))
note_paragraph = rows[1].cells[0].paragraphs[0]
note_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
note_paragraph.add_run(" shows the total count of training events per center.")
builder.figure_number += 1
rows[0].cells[1].paragraphs[0].add_run().add_picture(event_counts_percent, width=Inches(2.5), height=Inches(2.5))
note_paragraph = rows[1].cells[1].paragraphs[0]
note_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
note_paragraph.add_run(" shows the percentage of all network training events occurring at each center.")
builder.figure_number += 1
# 2. Attended Events (Events with > 0 attendees)
rows[2].cells[0].paragraphs[0].add_run().add_picture(event_counts_attended_total, width=Inches(3))
note_paragraph = rows[3].cells[0].paragraphs[0]
note_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
note_paragraph.add_run(" shows the count of training events that had at least one attendee.")
builder.figure_number += 1
rows[2].cells[1].paragraphs[0].add_run().add_picture(event_counts_attended_percent, width=Inches(2.5), height=Inches(2.5))
note_paragraph = rows[3].cells[1].paragraphs[0]
note_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
note_paragraph.add_run(" shows the percentage of attended training events across the network.")
builder.figure_number += 1
# 3. Excluding First Steps
rows[4].cells[0].paragraphs[0].add_run().add_picture(event_counts_no_first_total, width=Inches(2.5))
note_paragraph = rows[5].cells[0].paragraphs[0]
note_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
note_paragraph.add_run(" shows the count of training events EXCLUDING 'First Steps'.")
builder.figure_number += 1
rows[4].cells[1].paragraphs[0].add_run().add_picture(event_counts_no_first_percent, width=Inches(2), height=Inches(2))
note_paragraph = rows[5].cells[1].paragraphs[0]
note_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
note_paragraph.add_run(" shows the percentage of training events EXCLUDING 'First Steps'.")
builder.figure_number += 1
# NEXT PAGE: Attended (No First Steps) and No First/No Pre
builder.add_page_break()
picture_table_p2 = builder.doc.add_table(rows=6, cols=2)
rows_p2 = picture_table_p2.rows
# 4. Excluding First Steps (Attended Only)
rows_p2[0].cells[0].paragraphs[0].add_run().add_picture(event_counts_no_first_attended_total, width=Inches(3))
note_paragraph = rows_p2[1].cells[0].paragraphs[0]
note_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
note_paragraph.add_run(" shows the count of attended training events, EXCLUDING 'First Steps'.")
builder.figure_number += 1
rows_p2[0].cells[1].paragraphs[0].add_run().add_picture(event_counts_no_first_attended_percent, width=Inches(2.5), height=Inches(2.5))
note_paragraph = rows_p2[1].cells[1].paragraphs[0]
note_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
note_paragraph.add_run(" shows the percentage of attended training events, EXCLUDING 'First Steps'.")
builder.figure_number += 1
# 5. Excluding First Steps and Pre-planning
rows_p2[2].cells[0].paragraphs[0].add_run().add_picture(event_counts_no_first_no_pre_total, width=Inches(3))
note_paragraph = rows_p2[3].cells[0].paragraphs[0]
note_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
note_paragraph.add_run(" shows the count of training events EXCLUDING 'First Steps' and 'Business Start-up/Preplanning'.")
builder.figure_number += 1
rows_p2[2].cells[1].paragraphs[0].add_run().add_picture(event_counts_no_first_no_pre_percent, width=Inches(2.5), height=Inches(2.5))
note_paragraph = rows_p2[3].cells[1].paragraphs[0]
note_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
note_paragraph.add_run(" shows the percentage of training events EXCLUDING 'First Steps' and 'Business Start-up/Preplanning'.")
builder.figure_number += 1
# 6. First Steps ONLY
rows_p2[4].cells[0].paragraphs[0].add_run().add_picture(event_counts_first_only, width=Inches(2))
note_paragraph = rows_p2[5].cells[0].paragraphs[0]
note_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
note_paragraph.add_run(" shows the count of training events per center including 'First Steps' ONLY.")
builder.figure_number += 1
rows_p2[4].cells[1].paragraphs[0].add_run().add_picture(event_counts_first_only_percent, width=Inches(2.5), height=Inches(2))
note_paragraph = rows_p2[5].cells[1].paragraphs[0]
note_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
note_paragraph.add_run(" shows the percentage of training events per center including 'First Steps' ONLY.")
builder.figure_number += 1
builder.add_page_break()
picture_table_p3 = builder.doc.add_table(rows=2, cols=2)
rows_p3 = picture_table_p3.rows
# 7. Excluding First Steps (Attended Only)
rows_p3[0].cells[0].paragraphs[0].add_run().add_picture(event_counts_first_pre_only, width=Inches(3))
note_paragraph = rows_p3[1].cells[0].paragraphs[0]
note_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
note_paragraph.add_run(" shows the count of training events per center including 'First Steps' and 'Business Start-up/Preplanning' ONLY.")
builder.figure_number += 1
rows_p3[0].cells[1].paragraphs[0].add_run().add_picture(event_counts_first_pre_only_percent, width=Inches(2.5), height=Inches(2.5))
note_paragraph = rows_p3[1].cells[1].paragraphs[0]
note_paragraph.add_run(f"Figure {desk_review_section_number}.{builder.current_section}.{builder.figure_number}").bold = True
note_paragraph.add_run(" shows the count of training events per center including 'First Steps' and 'Business Start-up/Preplanning' ONLY.")
builder.figure_number += 1
builder.current_section = old_section