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));
}
};
})();
相关推荐
内容概要:主要讲解JS代码实现excel宏编程,从基础到进阶,另外也可作为函数查找手册用,或者帮助文档用;使用JS代码宏编程的优势就是运行快、代码简单易上手、且由于代码提示作用使得代码编写极快。提高工作效率。 ...
纯html+js实现,无需服务端。 可用于管理后台简单的批量导入数据到后台。 支持将excel表格中的数据直接转化成json格式化
简单方便的jquery.table2excel.js 实现table导出到excel中,可以自行修改js代码
js-xlsx是一个适用于JavaScript的开源库,可以实现对Excel的读取、写入、转换等操作。它是一个非常强大的工具,适用于前端开发人员,能够在前端解决Excel数据的处理问题。 使用js-xlsx实现前端导出Excel文件的场景...
内容概要:主要讲解JS代码实现excel宏编程,从基础到进阶,另外也可作为函数查找手册用,或者帮助文档用;使用JS代码宏编程的优势就是运行快、代码简单易上手、且由于代码提示作用使得代码编写极快。提高工作效率。 ...
通过tableexport.js插件 实现 将页面表格内容 导入excel 功能实现,一个简单的demo,需要参考的可下载
于是自己就想想能不能用javascript自己写一个,然后就东拼西凑一些网上的可用代码自己写了个小工具,实现了用javascript读取EXCEL表的题库,然后实现自动出题复习并算分,不过由于需要用到IE的EXCEL AX控件,所以...
如果后台不提供导出excel表格的接口,那么我们js有自己的方法可以支持。操作简单,可封装。完全抛弃后台,自己展示,自己导出,非常实用,资源内包含demo,一目了然。(原生js浏览器全兼容)
一个类似excel的页面插件,基于jquery,基本包括excel的基本功能,下拉列表之类
这是一个JS工具类程序,可以将页面数据导出到excel表格,不使用后台代码。纯前端代码实现。简单实用
前端导出excel,所见即所得,可以设置不导出列,可以设置不导出列,可以设置不导出列,简单方便,注释详细
采用javaScript实现页面中表格的报表生成操作! 非常方便和适用! 适合java开发者去简单实现报表操作 相互学习
本文介绍了关于利用JS实现同Excel表现的智能填充算法的相关内容,分享出供大家参考学习,下面话不多说了,来一起看看详细的介绍吧 在使用Excel的时候,发现它的“智能填充”功能非常有趣,能够智能地分析我当前的...
有时开发者只是想利用浏览器编制一些简单的脚本完成一些任务,不想学习C、C++、Python生成exe这么大动作,例如使用JavaScript脚本读取本地一个excel文件进行统计分析。但由于浏览器无法使用本地文件这个限制,只好...
本文给大家记录的是个人项目中遇到的,使用node.js实现Excel转换成Json的方法和过程,十分的简单实用,也很详细,这里推荐给有需要的小伙伴参考下。
内容概括:最近做的项目涉及到了excel的导出,在这块真的花了很多的时间,起初需求是不需要样式层面的修改的,所以选择了XLSX.JS,没有过多的去考虑样式的修改。但是随着项目进行,客户又提出了需要按照格式修改样式...
发现google sheet实现了excel的纯文本的多数据格粘贴,没有安全限制的需要,没有使用flash。可能很多人都知道这种方法了,反正我一开始很惊讶的,但是无奈,google的js文件是处理过的,看起来太累了。然后又去找...
这是我在javaeye看到一位楼主分享的帖子,的确是简单不华丽但却实用,所以保存成了TXT文档,并且更名为JS黄金宝典,对于我们这种初学JS的菜鸟来说,这本文档能帮上太大的忙了。关于收分的情况,请谅解,我是个菜鸟,...
vue3+pdf.js实现导入导出在线编辑pdf文件 该项目涵盖了excel导入,在线编辑,导出与pdf导入简单编辑导出两个功能 下载下来 执行 pnpm i pnpm run dev 如果想查看pdf在线编辑可以把src下的pdf.vue文件重命名为App.vue...
在类的render函数中放置一个简单的input元素,并传递一个onChange处理函数 <input type="file" onChange={this.fileHandler.bind(this)} style={{"padding":"10px"}} /> 在onChange处理程