You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
149 lines
3.9 KiB
149 lines
3.9 KiB
import ExcelJS from 'exceljs/dist/es5/exceljs.browser'
|
|
import { mergeCells, saveAsExcel } from './utils'
|
|
import { WIDTH_RATIO } from './constants'
|
|
import plugins from './plugins'
|
|
|
|
const PLUGIN_FUNCS = ['workbookCreated', 'worksheetCreated', 'worksheetCompleted', 'workcellCreated']
|
|
const DEFAULT_WORKBOOK_OPTIONS = {
|
|
views: [{
|
|
x: 0, y: 0, width: 10000, height: 20000,
|
|
firstSheet: 0, activeTab: 1, visibility: 'visible'
|
|
}]
|
|
}
|
|
const DEFAULT_OPTIONS = {
|
|
workbook: DEFAULT_WORKBOOK_OPTIONS,
|
|
widthRatio: WIDTH_RATIO,
|
|
plugins: [...Object.values(plugins)]
|
|
}
|
|
|
|
export default class Table2Excel {
|
|
|
|
constructor (selector = 'table', options = {}) {
|
|
this.tables = Array.from(
|
|
typeof selector === 'string'
|
|
? document.querySelectorAll(selector)
|
|
: selector
|
|
)
|
|
|
|
this.options = Object.assign({}, DEFAULT_OPTIONS, options)
|
|
|
|
this.plugins = {}
|
|
PLUGIN_FUNCS.forEach(funName => {
|
|
this.plugins[funName] = this.options.plugins.filter(plugin => plugin[funName]).map(plugin => plugin[funName])
|
|
})
|
|
|
|
this.pluginContext = {}
|
|
}
|
|
|
|
_invokePlugin (func, context = {}) {
|
|
this.pluginContext = Object.assign({}, this.pluginContext, context)
|
|
this.plugins[func].forEach(handler => handler.call(this, this.pluginContext))
|
|
}
|
|
|
|
toExcel () {
|
|
const { tables, options } = this
|
|
const workbook = new ExcelJS.Workbook() // create workbook
|
|
|
|
Object.assign(workbook, options)
|
|
|
|
// workbookCreated plugins
|
|
this._invokePlugin('workbookCreated', { workbook, tables })
|
|
|
|
tables.forEach((table, index) => {
|
|
const worksheet = workbook.addWorksheet(`Sheet ${index + 1}`)
|
|
|
|
// worksheetCreated plugins
|
|
this._invokePlugin('worksheetCreated', { worksheet, table })
|
|
|
|
this.toSheet(table, worksheet)
|
|
|
|
// worksheetCompleted plugins
|
|
this._invokePlugin('worksheetCompleted', { worksheet, table })
|
|
})
|
|
|
|
return this.workbook = workbook
|
|
}
|
|
|
|
toSheet (table, worksheet) {
|
|
// get total cols and rows
|
|
const totalRows = table.rows.length
|
|
let totalCols = 0
|
|
|
|
if (table.rows.length > 0) {
|
|
for (let i = 0; i < table.rows[0].cells.length; i++) {
|
|
totalCols += table.rows[0].cells[i].colSpan
|
|
}
|
|
}
|
|
|
|
const cells = []
|
|
Array.from(table.rows).forEach(row => {
|
|
Array.from(row.cells).forEach(cell => {
|
|
cells.push({
|
|
rowRange: {},
|
|
colRange: {},
|
|
el: cell
|
|
})
|
|
})
|
|
})
|
|
|
|
// create matrix
|
|
const helperMatrix = []
|
|
|
|
for (let r = 0; r < totalRows; r++) {
|
|
const row = []
|
|
for (let c = 0; c < totalCols; c++) {
|
|
row.push({ cell: null })
|
|
}
|
|
helperMatrix.push(row)
|
|
}
|
|
|
|
|
|
// mark matrix
|
|
let cursor = 0
|
|
|
|
for (let r = 0; r < totalRows; r++) {
|
|
for (let c = 0; c < totalCols; c++) {
|
|
// skip if current matrix unit is already assigned
|
|
if (helperMatrix[r][c].cell) {
|
|
continue
|
|
}
|
|
|
|
// assign cell to current matrix unit
|
|
const cell = cells[cursor++]
|
|
const { rowSpan, colSpan } = cell.el
|
|
|
|
cell.rowRange = { from: r, to: r }
|
|
cell.colRange = { from: c, to: c }
|
|
|
|
for (let y = r; y < r + rowSpan; y++) {
|
|
for (let x = c; x < c + colSpan; x++) {
|
|
helperMatrix[y][x].cell = cell
|
|
cell.colRange.to = x
|
|
cell.rowRange.to = y
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// read matrix to sheet
|
|
cells.forEach(cell => {
|
|
const { rowRange, colRange, el } = cell
|
|
const { innerText } = el
|
|
const workcell = mergeCells(worksheet, colRange.from, rowRange.from, colRange.to, rowRange.to)
|
|
const cellStyle = getComputedStyle(el)
|
|
|
|
workcell.value = innerText
|
|
|
|
// workcellCreated
|
|
this._invokePlugin('workcellCreated', { workcell, cell: el, rowRange, colRange, cellStyle })
|
|
})
|
|
}
|
|
|
|
export (fileName, ext) {
|
|
if (!this.workbook) {
|
|
this.toExcel()
|
|
}
|
|
saveAsExcel(this.workbook, fileName, ext)
|
|
}
|
|
}
|
|
|