225 lines
6.3 KiB
JavaScript
225 lines
6.3 KiB
JavaScript
import * as XLSX from "xlsx";
|
|
import { PDFDocument, rgb, StandardFonts } from 'pdf-lib';
|
|
|
|
/**
|
|
* Export JSON data to CSV
|
|
* @param {Array} data - Array of objects to export
|
|
* @param {string} fileName - File name without extension
|
|
*/
|
|
export const exportToCSV = (data, fileName = "data") => {
|
|
const headers = Object.keys(data[0] || {});
|
|
const csvContent = [
|
|
headers.join(","), // header row
|
|
...data.map(row => headers.map(field => `"${row[field] ?? ""}"`).join(",")),
|
|
].join("\n");
|
|
|
|
const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" });
|
|
const url = URL.createObjectURL(blob);
|
|
const link = document.createElement("a");
|
|
link.href = url;
|
|
link.setAttribute("download", `${fileName}.csv`);
|
|
document.body.appendChild(link);
|
|
link.click();
|
|
document.body.removeChild(link);
|
|
};
|
|
|
|
/**
|
|
* Export JSON data to Excel
|
|
* @param {Array} data - Array of objects to export
|
|
* @param {string} fileName - File name without extension
|
|
*/
|
|
export const exportToExcel = (data, fileName = "data") => {
|
|
const ws = XLSX.utils.json_to_sheet(data);
|
|
const wb = XLSX.utils.book_new();
|
|
XLSX.utils.book_append_sheet(wb, ws, "Sheet1");
|
|
XLSX.writeFile(wb, `${fileName}.xlsx`);
|
|
};
|
|
|
|
/**
|
|
* Export JSON data to PDF using pdf-lib
|
|
* @param {Array} data - Array of objects to export
|
|
* @param {string} fileName - File name for the PDF (optional)
|
|
*/
|
|
const sanitizeText = (text) => {
|
|
if (!text) return "";
|
|
// Replace all non-ASCII characters with "?" or remove them
|
|
return text.replace(/[^\x00-\x7F]/g, "?");
|
|
};
|
|
|
|
export const exportToPDF = async (data, fileName = "data", columns = null, options = {}) => {
|
|
if (!data || data.length === 0) return;
|
|
|
|
const pdfDoc = await PDFDocument.create();
|
|
const font = await pdfDoc.embedFont(StandardFonts.Helvetica);
|
|
|
|
// Default options
|
|
const {
|
|
columnWidths = [], // array of widths per column
|
|
fontSizeHeader = 12,
|
|
fontSizeRow = 10,
|
|
rowHeight = 25,
|
|
} = options;
|
|
|
|
const pageWidth = 1000;
|
|
const pageHeight = 600;
|
|
let page = pdfDoc.addPage([pageWidth, pageHeight]);
|
|
const margin = 30;
|
|
let y = pageHeight - margin;
|
|
|
|
const headers = columns || Object.keys(data[0]);
|
|
|
|
// Draw headers
|
|
headers.forEach((header, i) => {
|
|
const x = margin + (columnWidths[i] ? columnWidths.slice(0, i).reduce((a, b) => a + b, 0) : i * 150);
|
|
page.drawText(header, { x, y, font, size: fontSizeHeader });
|
|
});
|
|
y -= rowHeight;
|
|
|
|
// Draw rows
|
|
data.forEach(row => {
|
|
headers.forEach((header, i) => {
|
|
const x = margin + (columnWidths[i] ? columnWidths.slice(0, i).reduce((a, b) => a + b, 0) : i * 150);
|
|
const text = row[header] || '';
|
|
page.drawText(text, { x, y, font, size: fontSizeRow });
|
|
});
|
|
y -= rowHeight;
|
|
|
|
if (y < margin) {
|
|
page = pdfDoc.addPage([pageWidth, pageHeight]);
|
|
y = pageHeight - margin;
|
|
}
|
|
});
|
|
|
|
const pdfBytes = await pdfDoc.save();
|
|
const blob = new Blob([pdfBytes], { type: 'application/pdf' });
|
|
const link = document.createElement('a');
|
|
link.href = URL.createObjectURL(blob);
|
|
link.download = `${fileName}.pdf`;
|
|
link.click();
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Export JSON data to PDF in a card-style format
|
|
* @param {Array} data - Array of objects to export
|
|
* @param {string} fileName - File name for the PDF (optional)
|
|
*/
|
|
export const exportToPDF1 = async (data, fileName = "data") => {
|
|
if (!data || data.length === 0) return;
|
|
|
|
const pdfDoc = await PDFDocument.create();
|
|
const font = await pdfDoc.embedFont(StandardFonts.Helvetica);
|
|
const boldFont = await pdfDoc.embedFont(StandardFonts.HelveticaBold);
|
|
|
|
const pageWidth = 600;
|
|
const pageHeight = 800;
|
|
const margin = 30;
|
|
const cardSpacing = 20;
|
|
const cardPadding = 10;
|
|
let page = pdfDoc.addPage([pageWidth, pageHeight]);
|
|
let y = pageHeight - margin;
|
|
|
|
for (const item of data) {
|
|
const title = item.ContactName || "";
|
|
const subtitle = `by ${item.CreatedBy || ""} on ${item.CreatedAt || ""}`;
|
|
const body = item.Note || "";
|
|
|
|
const cardHeight = 80 + (body.length / 60) * 14; // approximate height for body text
|
|
|
|
if (y - cardHeight < margin) {
|
|
page = pdfDoc.addPage([pageWidth, pageHeight]);
|
|
y = pageHeight - margin;
|
|
}
|
|
|
|
// Draw card border
|
|
page.drawRectangle({
|
|
x: margin,
|
|
y: y - cardHeight,
|
|
width: pageWidth - 2 * margin,
|
|
height: cardHeight,
|
|
borderColor: rgb(0.7, 0.7, 0.7),
|
|
borderWidth: 1,
|
|
color: rgb(1, 1, 1),
|
|
});
|
|
|
|
// Draw title
|
|
page.drawText(title, {
|
|
x: margin + cardPadding,
|
|
y: y - 20,
|
|
font: boldFont,
|
|
size: 12,
|
|
color: rgb(0.1, 0.1, 0.1),
|
|
});
|
|
|
|
// Draw subtitle
|
|
page.drawText(subtitle, {
|
|
x: margin + cardPadding,
|
|
y: y - 35,
|
|
font,
|
|
size: 10,
|
|
color: rgb(0.4, 0.4, 0.4),
|
|
});
|
|
|
|
// Draw body text (wrap manually)
|
|
const lines = body.match(/(.|[\r\n]){1,80}/g) || [];
|
|
lines.forEach((line, i) => {
|
|
page.drawText(line, {
|
|
x: margin + cardPadding,
|
|
y: y - 50 - i * 12,
|
|
font,
|
|
size: 10,
|
|
color: rgb(0.2, 0.2, 0.2),
|
|
});
|
|
});
|
|
|
|
y -= cardHeight + cardSpacing;
|
|
}
|
|
|
|
const pdfBytes = await pdfDoc.save();
|
|
const blob = new Blob([pdfBytes], { type: 'application/pdf' });
|
|
const link = document.createElement('a');
|
|
link.href = URL.createObjectURL(blob);
|
|
link.download = `${fileName}.pdf`;
|
|
link.click();
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Print the HTML table by accepting the table element or a reference.
|
|
* @param {HTMLElement} table - The table element (or ref) to print
|
|
*/
|
|
export const printTable = (table) => {
|
|
if (table) {
|
|
const clone = table.cloneNode(true);
|
|
// Remove last column (Actions) from all rows
|
|
clone.querySelectorAll("tr").forEach((row) => {
|
|
row.removeChild(row.lastElementChild);
|
|
});
|
|
|
|
const newWindow = window.open("", "", "width=600,height=600");
|
|
newWindow.document.write("<html><head><title>Print Table</title>");
|
|
const style = document.createElement('style');
|
|
style.innerHTML = `
|
|
body { font-family: Arial, sans-serif; }
|
|
table { border-collapse: collapse; width: 100%; }
|
|
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
|
|
th { background-color: #f2f2f2; }
|
|
`;
|
|
newWindow.document.head.appendChild(style);
|
|
|
|
newWindow.document.write("</head><body>");
|
|
newWindow.document.write(clone.outerHTML);
|
|
newWindow.document.write("</body></html>");
|
|
newWindow.document.close();
|
|
newWindow.onload = () => {
|
|
newWindow.print();
|
|
};
|
|
}
|
|
};
|
|
|