0% found this document useful (0 votes)
10 views4 pages

Code5 Legl

The document outlines a Python class, ReportGenerator, designed to generate various Excel reports based on conversion results and metadata. It includes methods for styling headers, adjusting column widths, filling rows based on status, and generating specific reports such as conversion summaries and metadata exports. The class also incorporates logging functionality to track the report generation process and handle exceptions.

Uploaded by

girish infa
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views4 pages

Code5 Legl

The document outlines a Python class, ReportGenerator, designed to generate various Excel reports based on conversion results and metadata. It includes methods for styling headers, adjusting column widths, filling rows based on status, and generating specific reports such as conversion summaries and metadata exports. The class also incorporates logging functionality to track the report generation process and handle exceptions.

Uploaded by

girish infa
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

1 hdr_style(ws, row: int, bg: str = CLR_HEADER_BLUE, bold=True, fg='FFFFFF'):

2 for cell in ws[row]:


3 [Link] = Font(bold=bold, color=fg, size=10)
4 [Link] = PatternFill(start_color=bg, end_color=bg, fill_type='solid')
5 [Link] = Alignment(horizontal='left', vertical='center', wrap_text=True)
6
7
8 def _auto_width(ws, min_w=10, max_w=80):
9 for col in [Link]:
10 col_letter = get_column_letter(col[0].column)
11 best = min_w
12 for cell in col:
13 if [Link]:
14 val_len = len(str([Link]))
15 if val_len > best:
16 best = val_len
17 ws.column_dimensions[col_letter].width = min(best + 2, max_w)
18
19
20 def _alt_row(ws, row: int, ncols: int):
21 if row % 2 == 0:
22 for c in range(1, ncols + 1):
23 [Link](row=row, column=c).fill = PatternFill(
24 start_color=CLR_ROW_ALT, end_color=CLR_ROW_ALT, fill_type='solid')
25
26
27 def _status_fill(status: str) -> PatternFill:
28 s = str(status).lower()
29 if 'success' in s or 'auto' in s or 'created' in s:
30 return PatternFill(start_color=CLR_SUCCESS, end_color=CLR_SUCCESS,
fill_type='solid')
31 if 'partial' in s or 'manual' in s or 'simulated' in s:
32 return PatternFill(start_color=CLR_PARTIAL, end_color=CLR_PARTIAL,
fill_type='solid')
33 return PatternFill(start_color=CLR_FAILED, end_color=CLR_FAILED, fill_type='solid')
34
35
36 class ReportGenerator:
37 def __init__(self, output_dir: Path, logger=None):
38 self.output_dir = output_dir
39 [Link] = logger
40 self.output_dir.mkdir(exist_ok=True)
41
42 def _log(self, level, message):
43 if [Link]:
44 getattr([Link], level)(message)
45
46 # ──────────────────────────── Public API ────────────────────────────────
47
48 def generate_all_reports(self, results: Dict, metadata: Dict, session_id: str) ->
Dict:
49 self._log('info', "GENERATING EXCEL REPORTS")
50 report_files = {}
51
52 try:
53 fn = self._gen_conversion_summary(results, metadata, session_id)
54 report_files['conversion_summary'] = fn
55 self._log('info', f" ✓ {fn}")
56 except Exception as e:
57 self._log('error', f" ✗ Summary report: {e}")
58
59 try:
60 fn = self._gen_metadata_export(metadata, session_id)
61 report_files['metadata_export'] = fn
62 self._log('info', f" ✓ {fn}")
63 except Exception as e:
64 self._log('error', f" ✗ Metadata report: {e}")
65
66 try:
67 fn = self._gen_manual_steps(results, session_id)
68 report_files['manual_steps'] = fn
69 self._log('info', f" ✓ {fn}")
70 except Exception as e:
71 self._log('error', f" ✗ Manual steps report: {e}")
72
73 try:
74 fn = self._gen_dax_report(results, metadata, session_id)
75 report_files['dax_formulas'] = fn
76 self._log('info', f" ✓ {fn}")
77 except Exception as e:
78 self._log('error', f" ✗ DAX report: {e}")
79
80 try:
81 fn = self._gen_field_catalog(metadata, session_id)
82 report_files['field_catalog'] = fn
83 self._log('info', f" ✓ {fn}")
84 except Exception as e:
85 self._log('error', f" ✗ Field catalog: {e}")
86
87 self._log('info', f"Generated {len(report_files)} reports")
88 return report_files
89
90 # ────────────────────── Report 1: Conversion Summary ────────────────────
91
92 def _gen_conversion_summary(self, results: Dict, metadata: Dict, session_id: str) ->
str:
93 fname = f"conversion_summary_{session_id}.xlsx"
94 fpath = self.output_dir / fname
95 wb = Workbook()
96 [Link]([Link])
97
98 self._summary_overview(wb.create_sheet("Overview"), results, metadata,
session_id)
99 self._summary_object_details(wb.create_sheet("All Objects"), results)
100 self._summary_pbi_objects(wb.create_sheet("PBI Objects Created"), results)
101 self._summary_connection_map(wb.create_sheet("Connection Mapping"), metadata)
102 self._summary_successful(wb.create_sheet("Successful"), results)
103 self._summary_partial(wb.create_sheet("Partial"), results)
104 self._summary_failed(wb.create_sheet("Failed"), results)
105
106 [Link](fpath)
107 return fname
108
109 def _summary_overview(self, ws, results, metadata, session_id):
110 stats = [Link]('statistics', {})
111 total = [Link]('total', 0)
112 s = [Link]('successful', 0)
113 p = [Link]('partial', 0)
114 f = [Link]('failed', 0)
115 rate = [Link]('success_rate', 0)
116
117 [Link] = "Overview"
118 ws['A1'] = 'TABLEAU → POWER BI CONVERSION SUMMARY'
119 ws['A1'].font = Font(size=14, bold=True, color='FFFFFF')
120 ws['A1'].fill = PatternFill(start_color=CLR_HEADER_BLUE,
end_color=CLR_HEADER_BLUE, fill_type='solid')
121 ws.merge_cells('A1:D1')
122
123 rows = [
124 ['SESSION ID', session_id],
125 ['Run Date', [Link]().strftime('%Y-%m-%d %H:%M:%S')],
126 ['', ''],
127 ['── CONVERSION STATISTICS ──', ''],
128 ['Total Objects', total],
129 ['✓ Successful', s],
130 ['◑ Partial', p],
131 ['✗ Failed', f],
132 ['Automation Rate', f"{rate:.1f}%"],
133 ['', ''],
134 ['── OBJECT BREAKDOWN (metadata) ──', ''],
135 ['Workbooks', len([Link]('workbooks', []))],
136 ['Datasources', len([Link]('datasources', []))],
137 ['Views', len([Link]('views', []))],
138 ['', ''],
139 ['── METADATA TOTALS ──', ''],
140 ['Total Worksheets', [Link]('summary', {}).get('total_worksheets', 0)],
141 ['Total Dashboards', [Link]('summary', {}).get('total_dashboards', 0)],
142 ['Total Calculated Fields', [Link]('summary',
{}).get('total_calculations', 0)],
143 ['Total Columns/Fields', [Link]('summary', {}).get('total_columns',
0)],
144 ['Total Connections', [Link]('summary', {}).get('total_connections',
0)],
145 ['Total Parameters', [Link]('summary', {}).get('total_parameters', 0)],
146 ['', ''],
147 ['── POWER BI OBJECTS CREATED ──', ''],
148 ['Datasets Created', sum(1 for d in [Link]('conversion_details', [])
149 if [Link]('result', {}).get('datasets_created', 0) >
0)],
150 ['Reports Created', sum(1 for d in [Link]('conversion_details', [])
151 if [Link]('result', {}).get('reports_created', 0) >
0)],
152 ['Auto-Converted Measures', sum(
153 len([c for c in [Link]('result', {}).get('converted_components', [])
154 if [Link]('type') == 'measure'])
155 for d in [Link]('conversion_details', []))],
156 ['Manual Measures Needed', sum(
157 len([c for c in [Link]('result', {}).get('unconverted_components', [])
158 if [Link]('type') == 'measure'])
159 for d in [Link]('conversion_details', []))],
160 ]
161
162 for i, row_data in enumerate(rows, start=2):
163 [Link](row=i, column=1, value=row_data[0]).font = Font(bold=True, size=10)
164 [Link](row=i, column=2, value=row_data[1]).font = Font(size=10)
165
166 ws.column_dimensions['A'].width = 35
167 ws.column_dimensions['B'].width = 30
168
169 def _summary_object_details(self, ws, results):
170 headers = ['Object Name', 'Type', 'Status', 'Conversion Rate',
171 'Components Auto', 'Components Manual',
172 'PBI Objects', 'Datasets Created', 'Measures Created', 'Reports
Created']
173 [Link](headers)
174 _hdr_style(ws, 1)
175 for i, det in enumerate([Link]('conversion_details', []), start=2):
176 r = [Link]('result', {})
177 auto = len([c for c in [Link]('converted_components', []) if [Link]('type') !=
'dataset'])
178 manual = len([Link]('unconverted_components', []))
179 row = [
180 [Link]('object', ''),
181 [Link]('type', '').upper(),
182 [Link]('status', '').upper(),
183 f"{[Link]('conversion_rate', 0):.1f}%",
184 auto,
185 manual,
186 len([Link]('powerbi_objects', [])),
187 [Link]('datasets_created', 0),
188 [Link]('measures_created', 0),
189 [Link]('reports_created', 0),
190 ]
191 [Link](row)
192 status_cell = [Link](row=i, column=3)
193 status_cell.fill = _status_fill([Link]('status', ''))
194 _alt_row(ws, i, len(headers))
195 _auto_width(ws)
196
197 def _summary_pbi_objects(self, ws, results):
198 headers = ['Tableau Object', 'Type', 'PBI Object Name', 'PBI Object Type',
199 'PBI Object ID', 'Tables/Pages', 'Columns', 'Status']
200 [Link](headers)
201 _hdr_style(ws, 1)
202 row_idx = 2
203 for det in [Link]('conversion_details', []):
204 obj_name = [Link]('object', '')
205 obj_type = [Link]('type', '')
206 for pbi in [Link]('result', {}).get('powerbi_objects', []):
207 [Link]([
208 obj_name,
209 obj_type.upper(),
210 [Link]('name', ''),
211 [Link]('type', '').upper(),
212 [Link]('id', ''),
213 [Link]('table_count', [Link]('pages_needed', '')),
214 [Link]('column_count', ''),
215 [Link]('status', ''),
216 ])
217 [Link](row=row_idx, column=8).fill = _status_fill([Link]('status', ''))
218 row_idx += 1
219 _auto_width(ws)
220
221 def _summary_connection_map(self, ws, metadata):
222 headers = ['Workbook / Datasource', 'Tableau Connection Type', 'Power BI
Equivalent',
223 'Server', 'Database', 'Port', 'Schema', 'Action Required']
224 [Link](headers)
225 _hdr_style(ws, 1, CLR_HEADER_PURPLE)
226 row_idx = 2

You might also like