var TableApi;
(function () {
var MyDom = Helper.Dom;
var MyCore = Helper.Core;
TableApi = {
/**
* 获取table元素的单元格分布矩阵
* @param table
*/
getMatrix : function (table) {
var matrix = [];
for (var rowIndex = 0, rCnt = table.rows.length; rowIndex < rCnt; rowIndex++) {
if (!matrix[rowIndex]) {
matrix[rowIndex] = [];
}
for (var cellIndex = 0, cCnt = table.rows[rowIndex].cells.length; cellIndex < cCnt; cellIndex++) {
var columnIndex = cellIndex;
//In case there's are any horizontal or vertical spans before this cell
while (matrix[rowIndex][columnIndex]) {
columnIndex++;
}
var cell = table.rows[rowIndex].cells[cellIndex];
//Fill the corresponding matrix points
for (var i = 0; i < cell.rowSpan; i++) {
if (!matrix[rowIndex + i]) {
matrix[rowIndex + i] = [];
}
for (var j = 0; j < cell.colSpan; j++) {
matrix[rowIndex + i][columnIndex + j] = cell;
}
}
}
}
return matrix;
},
/**
* 合并单元格分布矩阵中选中的单元格
* @param matrix
*/
merge : function (matrix) {
var maxRowIndex = 0;
var minRowIndex = matrix.length - 1;
var maxColumnIndex = 0;
var minColumnIndex = matrix[0].length - 1;
var rowIndex, columnIndex, rCnt, cCnt;
//decide if selected cells region is mergable
for (rowIndex = 0,rCnt = matrix.length; rowIndex < rCnt; rowIndex++) {
for (columnIndex = 0,cCnt = matrix[0].length; columnIndex < cCnt; columnIndex++) {
if ($(matrix[rowIndex][columnIndex]).hasClass('selected')) {
if (rowIndex > maxRowIndex) {
maxRowIndex = rowIndex;
}
if (rowIndex < minRowIndex) {
minRowIndex = rowIndex;
}
if (columnIndex > maxColumnIndex) {
maxColumnIndex = columnIndex;
}
if (columnIndex < minColumnIndex) {
minColumnIndex = columnIndex;
}
}
}
}
var mergable = true;
for (rowIndex = minRowIndex; rowIndex <= maxRowIndex && mergable; rowIndex++) {
for (columnIndex = minColumnIndex; columnIndex <= maxColumnIndex; columnIndex++) {
if (!$(matrix[rowIndex][columnIndex]).hasClass('selected')) {
mergable = false;
break;
}
}
}
if (mergable) {
//then merge
var cellToMergeInto = matrix[minRowIndex][minColumnIndex];
for (rowIndex = minRowIndex; rowIndex <= maxRowIndex; rowIndex++) {
for (columnIndex = minColumnIndex; columnIndex <= maxColumnIndex; columnIndex++) {
var cell = matrix[rowIndex][columnIndex];
if (cell !== cellToMergeInto) {
for (var i = 0; i < cell.rowSpan; i++) {
for (var j = 0; j < cell.colSpan; j++) {
matrix[rowIndex + i][columnIndex + j] = cellToMergeInto;
}
}
MyDom.removeEl(cell);
}
}
}
cellToMergeInto.colSpan = (maxColumnIndex - minColumnIndex) + 1;
cellToMergeInto.rowSpan = (maxRowIndex - minRowIndex) + 1;
this.cleanUpEmptyRowsAndColumns(matrix);
}
return mergable;
},
/**
* 在单元格分布矩阵中指定行中搜索指定列的前一个单元格
* @param matrix
* @param rowIndex
* @param columnIndex
*/
searchForPreviousCellInRow : function (matrix, rowIndex, columnIndex) {
var columnIndexForPreviousCell = columnIndex;
var previousCell = null;
do{
columnIndexForPreviousCell -= 1;
previousCell = matrix[rowIndex][columnIndexForPreviousCell];
}
while (previousCell && (previousCell.parentNode.rowIndex !== rowIndex));
return previousCell;
},
/**
* 还原合并的单元格
* @param cell
*/
revertMerged : function (cell) {
var table = MyDom.searchUpByTagName(cell, 'TABLE');
var matrix = this.getMatrix(table);
var rowIndex = cell.parentNode.rowIndex;
var columnIndex = matrix[rowIndex].indexOf(cell);
var jCell = $(cell);
var tableApi = this;
MyCore.repeat(cell.colSpan - 1, function () {
jCell.after('<td>');
});
MyCore.repeat(cell.rowSpan - 1, function (time) {
var previousCell = tableApi.searchForPreviousCellInRow(matrix, rowIndex + time, columnIndex);
var task = null;
if (previousCell) {
var jPreviousCell = $(previousCell);
task = function () {
jPreviousCell.after('<td>');
};
}
else {
var jRow = $(table.rows[rowIndex + time]);
task = function () {
jRow.prepend('<td>');
};
}
MyCore.repeat(cell.colSpan, task);
});
cell.colSpan = cell.rowSpan = 1;
},
/**
* 清理单元格分布矩阵中的空行空列
* @param matrix
* @requires the matrix must reflect the current state of the table
*/
cleanUpEmptyRowsAndColumns : function (matrix) {
var table = matrix[0][0].parentNode.parentNode.parentNode;
var rowIndex, columnIndex, cell, cellToCollapse<script src="/javascripts/tinymce/themes/advanced/langs/zh.js" type="text/javascript"><!--mce:0--></script><script src="/javascripts/tinymce/plugins/javaeye/langs/zh.js" type="text/javascript"><!--mce:1--></script>, rCnt, cCnt;
cCnt = matrix[0].length;
//clean up empty rows
for (rowIndex = 0,rCnt = matrix.length; rowIndex < rCnt; rowIndex++) {
var isEmptyRow = true;
for (columnIndex = 0; columnIndex < cCnt; columnIndex++) {
cell = matrix[rowIndex][columnIndex];
if (cell.rowSpan === 1 || cell.parentNode.rowIndex === rowIndex) {
isEmptyRow = false;
break;
}
}
if (!isEmptyRow) {
continue;
}
//recalculate the rowspan
columnIndex = 0;
do{
cellToCollapse = matrix[rowIndex][columnIndex];
cellToCollapse.rowSpan -= 1;
columnIndex += cellToCollapse.colSpan;
}
while (columnIndex < cCnt);
//remove empty tr element
var row = table.rows[rowIndex];
MyDom.removeEl(row);
//remove empty row from matrix
for (var i = rowIndex, iLen = rCnt - 1; i < iLen; i++) {
matrix[i] = matrix[i + 1];
}
matrix.length -= 1;
rCnt--;
//cuz the original next row is now the current row
rowIndex--;
}
//clean up empty columns
for (columnIndex = 0; columnIndex < cCnt; columnIndex++) {
var isEmptyColumn = true;
for (rowIndex = 0; rowIndex < rCnt; rowIndex++) {
cell = matrix[rowIndex][columnIndex];
if (cell.colSpan === 1 || matrix[rowIndex][columnIndex + cell.colSpan - 1] === cell) {
isEmptyColumn = false;
break;
}
}
if (!isEmptyColumn) {
continue;
}
//recalculate the colspan
rowIndex = 0;
do{
cellToCollapse = matrix[rowIndex][columnIndex];
cellToCollapse.colSpan -= 1;
rowIndex += cellToCollapse.rowSpan;
}
while (rowIndex < rCnt);
//remove empty column from matrix
for (rowIndex = 0; rowIndex < rCnt; rowIndex++) {
for (var j = columnIndex, jLen = cCnt - 1; j < jLen; j++) {
matrix[rowIndex][j] = matrix[rowIndex][j + 1];
}
matrix[rowIndex].length -= 1;
}
cCnt--;
//remove corresponding col from colgroup if one exists
var colGroup = $('colgroup', table).get(0);
if (colGroup && colGroup.parentNode === table) {
MyDom.removeEl($('col:eq(' + columnIndex + ')', colGroup).get(0));
}
//cuz the original next column is now the current column
columnIndex--;
}
},
/**
* 根据指定的单元格和坐标获取在单元格分布矩阵中的精确位置
* @param matrix
* @param cell
* @param pageX
* @param pageY
*/
getAccuratePositionInMatrix : function (matrix, cell, pageX, pageY) {
var rowIndex = -1;
var columnIndex = -1;
var found, i, j, jCell, offset, iLen;
if (cell.colSpan === 1) {
columnIndex = matrix[cell.parentNode.rowIndex].indexOf(cell);
}
else {
var firstApperanceColumnIndex = matrix[cell.parentNode.rowIndex].indexOf(cell);
found = false;
//search for a single-column cell within the same column as the multi-column cell, which cuts through pageX horizontally.
for (j = firstApperanceColumnIndex; !found && j < firstApperanceColumnIndex + cell.colSpan; j++) {
for (i = 0,iLen = matrix.length; i < iLen; i++) {
if (matrix[i][j].colSpan !== 1) {
continue;
}
jCell = $(matrix[i][j]);
offset = jCell.offset();
if (offset.left <= pageX && offset.left + jCell.width() >= pageX) {
columnIndex = j;
found = true;
}
break;
}
}
if (!found) {
columnIndex = firstApperanceColumnIndex;
}
}
if (cell.rowSpan === 1) {
rowIndex = cell.parentNode.rowIndex;
}
else {
found = false;
var jLen = matrix[0].length;
//search for a single-row cell within the same row as the multi-row cell, which cuts through pageY vertically.
for (i = cell.parentNode.rowIndex; !found && i < cell.parentNode.rowIndex + cell.rowSpan; i++) {
for (j = 0; j < jLen; j++) {
if (matrix[i][j].rowSpan !== 1) {
continue;
}
jCell = $(matrix[i][j]);
offset = jCell.offset();
if (offset.top <= pageY && offset.top + jCell.height() >= pageY) {
rowIndex = i;
found = true;
}
break;
}
}
if (!found) {
rowIndex = cell.parentNode.rowIndex;
}
}
return {
rowIndex : rowIndex,
columnIndex : columnIndex
};
},
/**
* 重设列宽度
* @param table
* @param columnIndex
* @param width
*/
resizeColumn : function (table, columnIndex, width) {
//Notice that IE6 has problem with applying column width solely by col element. Set table-layout to fixed will solve this problem.
$('colgroup:first col:eq(' + columnIndex + ')', table).css('width', width);
},
/**
* 重设行高度
* @param table
* @param rowIndex
* @param height
*/
resizeRow : function (table, rowIndex, height) {
$('tbody:eq(0) > tr:eq(' + rowIndex + ')', table).css('height', height);
},
/**
* 计算获得table元素的行和列的位置偏移量
* @param matrix
*/
getOffsetsToTableForColumnAndRow : function (matrix) {
var columnOffsets = []; // the offset for the left edge of the columns
var rowOffsets = []; //the offset for the top edge of the rows
var tableOffset = $(MyDom.searchUpByTagName(matrix[0][0], 'TABLE')).offset();
var cell;
var
rCnt = matrix.length,
cCnt = matrix[0].length;
for (var rowIndex = 0; rowIndex < rCnt; rowIndex++) {
for (var columnIndex = 0; columnIndex < cCnt; columnIndex++) {
if (!columnOffsets[columnIndex]) {
cell = matrix[rowIndex][columnIndex];
if (cell.colSpan === 1 || matrix[rowIndex][columnIndex + cell.colSpan - 1] === cell) {
columnOffsets[columnIndex] = $(cell).offset().left - tableOffset.left;
}
}
if (!rowOffsets[rowIndex]) {
cell = matrix[rowIndex][columnIndex];
if (cell.rowSpan === 1 || cell.parentNode.rowIndex === rowIndex) {
rowOffsets[rowIndex] = $(cell).offset().top - tableOffset.top;
}
}
}
}
return {
columnOffsets : columnOffsets,
rowOffsets : rowOffsets
};
},
/**
* 在单元格所在列右边插入新列
* @param cell
* @param width
*/
insertColumnAfterCell : function (cell, width) {
var table = MyDom.searchUpByTagName(cell, 'TABLE');
var matrix = this.getMatrix(table);
var columnIndex = matrix[cell.parentNode.rowIndex].indexOf(cell) + cell.colSpan - 1;
//if the current column isn't the last column
if (columnIndex < matrix[0].length - 1) {
for (var rowIndex = 0, rCnt = matrix.length; rowIndex < rCnt; rowIndex++) {
var currentCell = matrix[rowIndex][columnIndex];
if (currentCell !== matrix[rowIndex][columnIndex + 1]) {
$(currentCell).after('<td>');
for (var i = 1; i < currentCell.rowSpan; i++) {
var previousCell = this.searchForPreviousCellInRow(matrix, rowIndex + i, columnIndex);
if (previousCell) {
$(previousCell).after('<td>');
}
else {
$(table.rows[rowIndex + i]).prepend('<td>');
}
}
}
else {
currentCell.colSpan++;
}
rowIndex += currentCell.rowSpan - 1;
}
}
else {
MyCore.each(table.rows, function (row) {
$(row).append('<td>');
});
}
$('col:eq(' + columnIndex + ')', table).after('<col style="width:' + width + 'px" />');
},
/**
* 在单元格所在列左边插入新列
* @param cell
* @param width
*/
insertColumnBeforeCell : function (cell, width) {
var table = MyDom.searchUpByTagName(cell, 'TABLE');
var matrix = this.getMatrix(table);
var columnIndex = matrix[cell.parentNode.rowIndex].indexOf(cell);
//if the current column isn't the first column
if (columnIndex > 0) {
for (var rowIndex = 0, rCnt = matrix.length; rowIndex < rCnt; rowIndex++) {
var currentCell = matrix[rowIndex][columnIndex];
if (currentCell !== matrix[rowIndex][columnIndex - 1]) {
$(currentCell).before('<td>');
for (var i = 1; i < currentCell.rowSpan; i++) {
var previousCell = this.searchForPreviousCellInRow(matrix, rowIndex + i, columnIndex);
if (previousCell) {
$(previousCell).after('<td>');
}
else {
$(table.rows[rowIndex + i]).prepend('<td>');
}
}
}
else {
currentCell.colSpan++;
}
rowIndex += currentCell.rowSpan - 1;
}
}
else {
MyCore.each(table.rows, function (row) {
$(row).prepend('<td>');
});
}
$('col:eq(' + columnIndex + ')', table).before('<col style="width:' + width + 'px" />');
},
/**
* 在单元格所在行下面插入新行
* @param cell
* @param height
*/
insertRowBelowCell : function (cell, height) {
var table = MyDom.searchUpByTagName(cell, 'TABLE');
var matrix = this.getMatrix(table);
var rowIndex = cell.parentNode.rowIndex + cell.rowSpan - 1;
var newRow = '<tr style="height:' + height + 'px">';
if (rowIndex < matrix.length - 1) {
for (var columnIndex = 0, cCnt = matrix[rowIndex].length; columnIndex < cCnt; columnIndex++) {
var currentCell = matrix[rowIndex][columnIndex];
if (currentCell !== matrix[rowIndex + 1][columnIndex]) {
MyCore.repeat(currentCell.colSpan, function () {
newRow += '<td></td>';
});
}
else {
currentCell.rowSpan++;
}
columnIndex += currentCell.colSpan - 1;
}
}
else {
MyCore.repeat(matrix[rowIndex].length, function () {
newRow += '<td></td>';
});
}
newRow += '</tr>';
$(table.rows[rowIndex]).after(newRow);
},
/**
* 在单元格所在行上面插入新行
* @param cell
* @param height
*/
insertRowAboveCell : function (cell, height) {
var table = MyDom.searchUpByTagName(cell, 'TABLE');
var matrix = this.getMatrix(table);
var rowIndex = cell.parentNode.rowIndex;
var newRow = '<tr style="height:' + height + 'px">';
if (rowIndex > 0) {
for (var columnIndex = 0, cCnt = matrix[rowIndex].length; columnIndex < cCnt; columnIndex++) {
var currentCell = matrix[rowIndex][columnIndex];
if (currentCell !== matrix[rowIndex - 1][columnIndex]) {
MyCore.repeat(currentCell.colSpan, function () {
newRow += '<td></td>';
});
}
else {
currentCell.rowSpan++;
}
columnIndex += currentCell.colSpan - 1;
}
}
else {
MyCore.repeat(matrix[rowIndex].length, function () {
newRow += '<td></td>';
});
}
newRow += '</tr>';
$(table.rows[rowIndex]).before(newRow);
},
/**
* 按照源table的尺寸更新目标table
* @param srcTable
* @param targetTable
*/
copySize : function (srcTable, targetTable) {
var targetCols = $('colgroup:first col', targetTable).get();
$('colgroup:first col', srcTable).each(function (index) {
targetCols[index].style.width = this.style.width;
});
var targetRows = $('tbody:first tr', targetTable).get();
$('tbody:first tr', srcTable).each(function (index) {
targetRows[index].style.height = this.style.height;
});
},
/**
* 移除单元格所在的行
* @param cell
*/
removeRow : function (cell) {
if (cell.rowSpan !== 1) {
throw 'The cell has to only belong to one row!';
}
var table = MyDom.searchUpByTagName(cell, 'TABLE');
if (table.rows.length === 1) {
throw '这是表中唯一的一行,不允许删除!';
}
var matrix = this.getMatrix(table);
var rowIndex = cell.parentNode.rowIndex;
for (var columnIndex = 0, cCnt = matrix[rowIndex].length; columnIndex < cCnt; columnIndex++) {
var currentCell = matrix[rowIndex][columnIndex];
if (currentCell.rowSpan > 1) {
currentCell.rowSpan -= 1;
if (currentCell.parentNode.rowIndex === rowIndex) {
var cellToInsertAfter = null;
for (var columnIndexOfTheRowBelow = columnIndex - 1; columnIndexOfTheRowBelow >= 0; columnIndexOfTheRowBelow--) {
var cellOfTheRowBelow = matrix[rowIndex + 1][columnIndexOfTheRowBelow];
if (cellOfTheRowBelow.rowSpan === 1 || cellOfTheRowBelow.parentNode.rowIndex === rowIndex + 1) {
cellToInsertAfter = cellOfTheRowBelow;
break;
}
}
var rowBelow = currentCell.parentNode.nextSibling;
if (cellToInsertAfter) {
rowBelow.insertBefore(currentCell, cellToInsertAfter.nextSibling);
}
else {
rowBelow.insertBefore(currentCell, rowBelow.firstChild);
}
}
}
columnIndex += currentCell.colSpan - 1;
}
MyDom.removeEl(table.rows[rowIndex]);
this.cleanUpEmptyRowsAndColumns(this.getMatrix(table));
},
/**
* 移除单元格所在的列
* @param cell
*/
removeColumn : function (cell) {
if (cell.colSpan !== 1) {
throw 'The cell has to only belong to one column!';
}
var table = MyDom.searchUpByTagName(cell, 'TABLE');
var matrix = this.getMatrix(table);
if (matrix[0].length === 1) {
throw '这是该表唯一的一列,不允许删除!';
}
var columnIndex = matrix[cell.parentNode.rowIndex].indexOf(cell);
for (var rowIndex = 0, rCnt = matrix.length; rowIndex < rCnt; rowIndex++) {
var currentCell = matrix[rowIndex][columnIndex];
if (currentCell.colSpan > 1) {
currentCell.colSpan -= 1;
}
else {
MyDom.removeEl(currentCell);
}
rowIndex += currentCell.rowSpan - 1;
}
MyDom.removeEl($('colgroup:first col:eq(' + columnIndex + ')', table).get(0));
this.cleanUpEmptyRowsAndColumns(this.getMatrix(table));
}
};
})();
相关推荐
JavaScript是网页开发中的主要脚本语言,通过`excel.js`,开发者可以利用JavaScript实现对Excel文件的读取、修改和保存,大大提高了数据处理的效率和用户体验。 `excel.js` 的核心功能包括: 1. **Excel导入**:...
当我们谈论“Export2Excel.js”时,我们关注的是一个利用JavaScript实现的功能,即从数据源导出到Excel电子表格。这个功能在数据分析、报表生成以及用户需要下载结构化数据的场景下非常常见。 首先,我们要理解...
使用JavaScript实现打印和导出为Excel是非常简单的,我们可以使用JavaScript来实现这两个功能,而不需要使用控件或POI。我们只需要使用JavaScript来获取当前页面的指定区域的innerHTML,然后将其包装为一个Excel文件...
Blob.js和Export2Excel.js是两个JavaScript库,专门用于处理这种需求。Blob.js提供了Blob对象的相关功能,而Export2Excel.js则实现了将HTML表格转换为Excel文件的功能。接下来,我们将深入探讨这两个库的工作原理和...
在本项目中,"nodejs基于excel.js实现超轻量级报表源码.rar" 提供了一个使用Node.js和excel.js库来创建轻量级报表的解决方案。以下是对这个主题的详细解析: 首先,Node.js是一种基于Chrome V8引擎的JavaScript运行...
在现代Web应用中,数据的...Blob.js处理二进制数据的能力结合Export2Excel.js的表格到Excel转换功能,使得在Vue.js应用中实现数据导出变得简单易行。开发者只需遵循一定的步骤,就能让用户提供便捷的表格数据下载体验。
以下是一些关于如何使用JavaScript实现这一功能的关键知识点: 1. **文件类型理解**:Excel文件通常以.xlsx或.xls格式存储,这两种都是微软的Microsoft Office Excel使用的文件扩展名。在Web环境中,我们无法直接...
简单方便的jquery.table2excel.js 实现table导出到excel中,可以自行修改js代码
使用jQuery.table2excel.js非常简单,主要分为以下几步: 1. **引入依赖**:在HTML文件中引入jQuery库和jQuery.table2excel.js插件的脚本文件。 2. **配置参数**:可以设置一些可选参数,如表格的CSS选择器、导出的...
总结来说,“Export2Excel.js”和“Blob.js”是Vue.js中处理数据导出的强大工具,它们使得前端开发者无需依赖服务器端支持就能实现数据的Excel导出,提高了应用的交互性和用户体验。理解并熟练运用这两个库,对于...
这可能通过JavaScript实现,例如遍历DOM元素来提取数据,或者如果数据是通过Ajax异步加载的,可以直接从缓存或API响应中获取。 2. **数据转换**:将获取的数据转换为Excel可以理解的格式。Excel文件本质上是XML格式...
接下来,我们需要引入`jquery.table2excel.js`,这是`jquery-table2excel`插件的主要源代码文件。这个插件的核心思想是利用浏览器的`data:`URI scheme和`window.navigator.msSaveBlob`(针对IE浏览器)或`a.download...
在这个名为"vue实现导出Excel的公用组件vendor"的案例中,我们主要涉及两个关键文件:Blob.js和Export2Excel.js。 Blob.js是JavaScript中的一个对象,它代表不可变的、原始数据的类文件对象。在Web开发中,Blob对象...
`js-xlsx`库提供了一种纯JavaScript的方式来读写Excel文件。它的API非常灵活,可以处理各种Excel格式。导出Excel文件时,需要创建一个工作表对象,然后加入到工作簿中,最后将其转换为二进制数据并下载。 ```...
本文将详细介绍如何使用JavaScript实现这一功能,以及相关知识点。 首先,我们需要理解JSON(JavaScript Object Notation)和Excel之间的差异。JSON是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器...
在JavaScript(JS)环境中,导出Excel数据是常见的需求,特别是在Web应用中,用户可能需要将数据下载到本地以便进一步处理或分析。本篇将详细讲解如何使用JS导出Excel插件来实现这一功能,以及如何配置这些插件应用...
接下来,我们将深入探讨Node.js如何简单读写Excel文件,以及其中常见的模块和实例操作技巧。 首先,node-xlsx是一个在Node.js中读写.xlsx格式Excel文件的模块。该模块提供了解析Excel文件数据和生成Excel文件的功能...
总之,通过`xlsx`库或其他类似的JS插件,我们可以轻松实现JavaScript环境中的Excel文件导入和导出功能。理解这些库的工作原理和API,结合实际项目需求,能够帮助你构建高效、健壮的数据处理系统。
在JavaScript(JS)环境中,处理Excel表格数据通常涉及到前端与后端的数据交互,以及解析Excel文件格式。在给定的标题和描述中,“js读取excel表格的js文件”反复提及,这暗示我们需要关注的是一个JavaScript库,...
本项目涉及的主题是“使用JavaScript读取Excel文件来实现药品临期和过期提醒”,这涉及到JavaScript与Excel数据交互的技术,以及前端界面的构建。我们将详细探讨以下几个关键知识点: 1. **JQuery库**:JQuery是...