在报告脚本中显示关系字段数据
用户希望报告能够让他们将所有关系字段数据导出到 Excel 工作表中。
例如:
<%version 1%>
<%description
<br>${DATA}$: </br>${ITEM_FIELDS}$
<br>
<br>${NOTES}$: </br>${DESCRIPTION_NOTES}$
<br>
%>
<%param
name="reporttitle"
type="String"
prompt="${REPORT_TITLE}$"
value=""
description="${REPORT_TITLE_DESCRIPTION}$"
%>
<%param
name="reportheader"
type="MultiString"
prompt="${REPORT_HEADER}$"
value=""
description="${REPORT_HEADER_DESCRIPTION}$"
%>
<%param
name="reportfooter"
type="MultiString"
prompt="${REPORT_FOOTER}$"
value=""
description="${REPORT_FOOTER_DESCRIPTION}$"
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>&reporttitle</title>
<%screenStyleSheet%>
<%printerStyleSheet%>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx-style/0.8.13 /xlsx.full.min.js"></script>
</head>
<%dateformat%>
<%datetimeformat%>
<%sortby &sortby%>
<body>
<table class="display" id="relationship-content-table">
<thead>
<tr>
<td colspan="&#fields">
<table class="display">
<tr>
<td class="logo">
<%logoURL%>
</td>
<td>
<div class="title">&reporttitle</div">
<p>
<div class="header">&reportheader</div">
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td colspan="&#fields" class="date">
<%currentdate%>
</td>
</tr>
<tr>
<td>
<hr class="hr_default">
</td>
</tr>
<tr>
<!-- Display issue field headings -->
<%iteratefields%>
<th class="heading1" rowspan="2" data-a-indent="3>&fielddisplayname</th>
<%/iteratefields%>
<th class="relationship-field-header heading1" rowspan="2" data-a-indent="3">
Relationship Tables
</th>
<tr>
<td>
<hr class="hr_default">
</td>
</tr>
</thead>
<tbody>
<!-- Display issue field values -->
<%begindetail%>
<tr class="odd_row">
<%iteratefields%>
<td class="border">&fieldname</td>
<%/iteratefields%>
<!-- Relationships info -->
<%segment
name="Relationships"
type="relationship"
enabled="true"
description="
<html>${RELATIONSHIPS_DESCRIPTION}$</html>"
%>
<%param name="norelationships"
type="String"
prompt="${NO_RELATIONSHIPS_MESSAGE}$"
value="${NO_RELATIONSHIPS_VALUE}$"
description="${NO_RELATIONSHIPS_DESCRIPTION}$
%>
<td class="border">
<table class="list">
<tr class="relationship-data-header">
<th colspan="&#fields">&relationshipdetailsfield:</th>
</tr>
<%beginrelationshipsdetail &relationshipdetailsfield%>
<%relationshipfilter%>
<%relationshipsortby &sortby%>
<!-- Display relationship issue field headings -->
<%beginrelationshipsection header%>
<tr class="table-row-header">
<%iteraterelationshipfields%>
<th class="table-column">&relationshipfielddisplayname</th>
<%/iteraterelationshipfields%>
</tr>
<%endrelationshipsdetail%>
<!-- Display no relationships found -->
<%beginrelationshipsection none%>
<tr class="table-row-no-data">
<td class="table-column">&relationshipfieldname</td>
<%/iteraterelationshipfields%>
</tr>
<%endrelationshipsdetail%>
<!-- Display relationship issue field values -->
<tr class="table-row-content">
<%iteraterelationshipfields%>
<td class="table-column">&relationshipfieldname</td>
<%/iteraterelationshipfields%>
</tr>
<%endrelationshipsdetail%>
</table>
</td>
<%/segment%>
</tr>
<tr>
<td>
<hr class="hr_default">
</td>
</tr>
<%enddetail%>
</tbody>
</table>
<button.id="button-excel">Export to Excel</button>
<script>
document.querySelector("#button-excel").addEventListener("click", function () {
// Reference to your table
let table = document.querySelector("#relationship-content-table");
let data = [];
let merges = []; // Store cell merge info
let mergedRequired = true;
let stopExecution = 0;
let relationshipData = [];
let relationshipTableRow = 0;
let relationshipTableColumn = 0;
let relationshipFieldIndex = 0;
let cellRef = null
const excludedClasses = ['table-row-header', 'table-row-content', 'table-row-no-data','relationship-data-header'];
// Loop through table rows
table.querySelectorAll("tr").forEach((row, rowIndex) => {
let rowData = [];
stopExecution = 0;
if (!excludedClasses.includes(row.className)) {
row.querySelectorAll("td, th").forEach((cell, colIndex) => {
let colspan = cell.getAttribute("colspan");
let rowspan = cell.getAttribute("rowspan");
// Add cell value
if (stopExecution == 0) {
if (cell.getElementsByClassName('table-row-content').length == 0) {
rowData.push(storeCellData.extractCellData(cell));
} else if (cell.getElementsByClassName('table-row-content').length > 0) {
stopExecution = 1;
relationshipTableRow = cell.getElementsByClassName('table-row-content').length + 1
relationshipTableColumn = cell.getElementsByClassName('table-column').length / relationshipTableRow;
}
relationshipFieldIndex = colIndex;
} else {
if (cell.colSpan <= 1) {
relationshipData.push(storeCellData.extractCellData(cell));
if (rowData.length == 0) {
for (let i=0; i<relationshipFieldIndex; i++)
// Adding blank cells
rowData.push("");
}
}
rowData.push(storeCellData.extractCellData(cell));
if (relationshipData.length == relationshipTableColumn) {
data.push(rowData);
relationshipData = [];
rowData = [];
}
} else {
rowData.push(storeCellData.extractCellData(cell));
data.push(rowData);
rowData = [];
if (colspan || rowspan) {
merges.push(storeMergedData.mergerdOperation(colspan, rowspan, colIndex - 1, data.length - 1)
mergedRequired = false}
}
}
}
if (mergedRequired) {
if (cell.className == 'relationship-field-header heading1' && (colIndex == document.getElementsByClassName('heading1').length - 1)) {
colspan = document.getElementsByClassName('table-column').length /
(document.getElementsByClassName('table-row-content').length + document.getElementsByClassName('table-row-header').length);
}
if (colspan || rowspan) {
merges.push(storeMergedData.mergerdOperation(colspan, rowspan, colIndex, rowIndex));
}
}
});
}
if (rowData.length > 0) {
data.push(rowData);
}
});
// Create a new workbook and worksheet
let ws = XLSX.utils.aoa_to_sheet(data);
// Apply cell merges
ws["!merges"] = merges;
// Apply hyperlinks
for (const cell in ws) {
if (ws.hasOwnProperty(cell) && cell[0] !== '!') {
const cellValue = ws[cell].v;
if (typeof cellValue === 'object' && cellValue.hyperlink) {
//ws[cell].t = "s"; // Text type
ws[cell].s = { font: { color: { rgb: "0000FF" }, underline: true } } // ���� Blue & Underlined
ws[cell].l = { Target: cellValue.hyperlink, Tooltip: cellValue.text };
ws[cell].v = cellValue.text;
}
}
}
// Create a workbook and append the worksheet
let wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, "Sheet1");
// Export the workbook
XLSX.writeFile(wb, "Report.xlsx");
});
const storeMergedData = {
mergerdOperation(colspan, rowspan, colIndex, rowIndex) {
return {
s: { r: rowIndex, c: colIndex }, // Start cell
e: {
r: rowspan ? rowIndex + parseInt(rowspan) - 1 : rowIndex,
c: colspan ? colIndex + parseInt(colspan) - 1 : colIndex
} // End cell
}
}
}
const storeCellData = {
extractCellData(cell) {
// Check for hyperlinks
const link = cell.querySelector('a');
if (link) {
return {
//t: "s", // Text type
s: { font: { color: { rgb: "0000FF" }, underline: true } }, // ���� Blue & Underlined
v: {text: link.innerText, hyperlink: link.href } }
};
} else {
return cell.innerText;
}
}
}
</script>
</body>
</html>