office EXCEL文档有合并表格功能,WPS基础功能免费,但合并表格要充SSSSSS VIP
我又没有office EXCEL,我又不想充 WPS VIP,所以我研究了这个用js合并的方法。
如果你对js和excel有兴趣,你也可以好好研究 js-xlsx,用代码去处理excel。代码的灵活性要比WPS强多了。
界面如图左侧所示。(右侧绿框是按F12弹出的调试界面,可显示调试信息)
按顺序操作1,2,3,4,5,即可拼接第1个表和第2个表。

(上图)左下角可生成示例用于拼接的表1和表2



如果能正常下载zip,下面内容可以不用看了。下载文件夹找到直接双击join.htm即可使用。
1、新建文件夹(任意名字,任意目录),例如叫‘js处理excel’,放桌面

2、其中,join.htm是我参照别人写的‘网页’,xlsxtool.js是工具文件(实际这里文件都是txt文档-纯文本,然后修改后缀,.txt改为.htm,.js。)
后面会给出join.htm,xlsxtool.js的代码。
【js】这个目录/文件夹,就必须起'js'这个名字(否则你就要改代码里的引用路径)并放在'js处理excel'目录下。
【js】里面是三个js文件,其中1,2是网上下载的官方工具插件,3是我抄写的工具。



不要看到‘代码’就害怕,无非都是一些txt纯文本,只不过有固定格式而已,然后把后缀'xxx.txt'改成'xxx.htm','xxx.js'而已
join.htm
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<!-- 网络加载 jquery -->
<!-- <script src="https://code.jquery.com/jquery-3.0.0.min.js" integrity="sha256-JmvOoLtYsmqlsWxa7mDSLMwa6dZ9rrIdtrrVYRnDRH0=" crossorigin="anonymous"></script> -->
<!-- 本地jquery -->
<script src="js/jquery-3.0.0.min.js"></script>
<script src="js/xlsx.core.min.js"></script>
<script src="js/xlsxtool.js"></script>
</head>
<body>
<p id="p1">第1个表</p>
<input type="file" id="excel-file1" name="">
<p id="p2">第2个表</p>
<input type="file" id="excel-file2" name="">
<p><a style="color:blue;">ID</a>(匹配字段-2个表中相同的列名称,如2个表的学生学号一致且值唯一,就填"<a style="color:red;">学号</a>")</p>
<p style="font-size: smaller">表1第1行和表2哪一行拼接呢?那肯定是张三的成绩拼到张三那一行啊!但学校可能有2个张三,但学号是唯一的,所以用学号做ID(数据匹配依据)</p>
<input type="text" id="tbID" placeholder="2个表相同且值唯一的列名">
<p><a style="color:blue;">拼接字段</a>(第2个表参与拼接的列,如要把第2个表的数学、语文列拼接到新表,则填"<a style="color:red;">数学,语文</a>",中间逗号隔开)</p>
<input type="text" id="appends" placeholder="新增列名1,列名2,..">
<p>拼接2个表</p>
<button type="button" onclick="clickJoin(this)">拼接2个成表</button>
<p class="tips">测试数据-示例</p>
<button class="btn-gen1" type="button" onclick="clickGenTable1(this)">下载学生表</button>
<button class="btn-gen2" type="button" onclick="clickGenTable2(this)">下载学生成绩表</button>
</body>
<script>
$('#excel-file1').change(function (e) {
document.getElementById('p1').innerHTML = '第1个表(已获取)'
var files = e.target.files;
var fileReader = new FileReader();
fileReader.onload = function (ev) {
try {
var data = ev.target.result,
workbook = XLSX.read(data, {
type: 'binary'
}), // 以二进制流方式读取得到整份excel表格对象
persons = []; // 存储获取到的数据
} catch (e) {
console.log('文件类型不正确');
return;
}
// 表格的表格范围,可用于判断表头是否数量是否正确
var fromTo = '';
// 遍历每张表读取
// !!!workbook.Sheets是一个对象!!不是数组!
console.log('=====workbook1=====:')
console.log(workbook)
for (var propertyName in workbook.Sheets) {
console.log('propertyName: ' + propertyName)
if (workbook.Sheets.hasOwnProperty(propertyName)) {
var sheet = workbook.Sheets[propertyName]
// console.log(sheet)
fromTo = sheet['!ref'];
console.log('fromTo: ' + fromTo);
firstTableRows = XLSX.utils.sheet_to_json(sheet)
persons = persons.concat(firstTableRows);
break; // 如果只取第一张表,就取消注释这行
}
}
console.log('表-json对象1:');
console.log(firstTableRows);
// let jsonString = JSON.stringify(firstTableRows)
// console.log(jsonString);
};
// 以二进制方式打开文件
fileReader.readAsBinaryString(files[0]);
});
$('#excel-file2').change(function (e) {
document.getElementById('p2').innerHTML = '第2个表(已获取)'
var files = e.target.files;
var fileReader = new FileReader();
fileReader.onload = function (ev) {
try {
var data = ev.target.result,
workbook = XLSX.read(data, {
type: 'binary'
}), // 以二进制流方式读取得到整份excel表格对象
persons = []; // 存储获取到的数据
} catch (e) {
console.log('文件类型不正确');
return;
}
// 表格的表格范围,可用于判断表头是否数量是否正确
var fromTo = '';
// 遍历每张表读取
// !!!workbook.Sheets是一个对象!!不是数组!
console.log('=====workbook2=====:')
console.log(workbook)
for (var propertyName in workbook.Sheets) {
console.log('propertyName: ' + propertyName)
if (workbook.Sheets.hasOwnProperty(propertyName)) {
var sheet = workbook.Sheets[propertyName]
// console.log(sheet)
fromTo = sheet['!ref'];
console.log('fromTo: ' + fromTo);
secondTableRows = XLSX.utils.sheet_to_json(sheet)
persons = persons.concat(secondTableRows);
break; // 如果只取第一张表,就取消注释这行
}
}
console.log('表-json对象2:');
console.log(secondTableRows);
};
// 以二进制方式打开文件
fileReader.readAsBinaryString(files[0]);
});
function clickJoin(argument) {
// body...
console.log('点击了‘拼接’按钮')
// jsonToExcel( sheet1data, 'demo.xls');
// testGen()
if(!firstTableRows) {
alert('请先选择第1个表')
}else if(!secondTableRows) {
alert('请先选择第2个表')
}else {
let idStr = document.getElementById('tbID').value
console.log(idStr)
let appends = document.getElementById('appends').value
console.log(appends)
if (!idStr) {
alert('请先填写ID')
return
}
if(!appends) {
alert('请先填写拼接字段')
return
}
let appendsArr = []
if(appends.indexOf(',') != -1) {
appendsArr = appends.split(',')
}else if(appends.indexOf(',') != -1) {
appendsArr = appends.split(',')
}else if(appends.indexOf(';') != -1) {
appendsArr = appends.split(';')
}else if(appends.indexOf(';') != -1) {
appendsArr = appends.split(';')
}else {
appendsArr.push(appends)
}
console.log(appendsArr)
for (var i = 0; i < firstTableRows.length; i++) {
let t1row = firstTableRows[i]
for (var j = 0; j < secondTableRows.length; j++) {
let t2row = secondTableRows[j]
// if(t2row['学号'] == t1row['学号']) {
// t1row['语文'] = t2row['语文']
// t1row['数学'] = t2row['数学']
// }
if (t2row[idStr] == t1row[idStr]) {
for (var k = 0; k < appendsArr.length; k++) {
let key = appendsArr[k]
// console.log('key = ' + key)
if (t2row[key] !== undefined) {
t1row[key] = t2row[key]
}
}
}
}
}
xtGenExcel(firstTableRows, '拼接表')
}
}
function clickGenTable1(argument) {
// body...
testGenStudents()
}
function clickGenTable2(argument) {
// body...
testGenResults()
}
// demo调用演示
let sheet1data = [ // 注意数组中每列key的排序,因为导出列表时按照key的排序导出的
{ 部门: '行政部', 姓名: 'zhangsan', age: 18 },
{ 部门: 'IT', 姓名: 'lisi', age: 19 },
];
var firstTableRows = undefined
var secondTableRows = undefined
</script>
<style type="text/css">
.tips {
position: fixed;
bottom: 30px;
left: 20px;
color: #333333;
font-size: small;
}
.btn-gen1 {
position: fixed;
bottom: 10px;
left: 20px;
color: blue;
}
.btn-gen2 {
position: fixed;
bottom: 10px;
left: 120px;
color: blue;
}
</style>
</html>
xlsxtool.js
// 导入文件
document.write("<script language = javascript src = 'js/xlsx.core.min.js'></script>")
function testGen() {
// body...
xtGenExcel(testData)
}
function testGenStudents() {
// body...
xtGenExcel(students, '学生表')
}
function testGenResults() {
// body...
xtGenExcel(examResults, '学生成绩表')
}
function xtGenExcel(rows, bookName = 'MYBOOK', sheetName = 'sheet1') {
// body...
const workbook = XLSX.utils.book_new();
const worksheet = XLSX.utils.json_to_sheet(rows);
XLSX.utils.book_append_sheet(workbook, worksheet, sheetName);
// 给 sheet 添加【表头】
// XLSX.utils.sheet_add_aoa(worksheet, [["Name", "Birthday"]], { origin: "A1" });
// 调整适应列宽
// const max_width = rows.reduce((w, r) => Math.max(w, r.name.length), 10);
// 第一列列宽 = max_width, 第二列列宽 = 10。 wch:
// worksheet["!cols"] = [ { wch: max_width } , {wch: 10}];
// 输出 excel
XLSX.writeFile(workbook, bookName + ".xlsx", { compression: true });
}
// 这个方法不需要 xlsx 插件。
function jsonToExcel(jsonData, filename = 'export.xls') {
if (!Array.isArray(jsonData) || !jsonData?.length) {
return;
}
let str = '';
// 列标题
Object.keys(jsonData[0]).forEach(k => {
str += k + '\t,';
});
str += '\n';
// 增加\t为了不让表格显示科学计数法或者其他格式
for (let i = 0; i < jsonData.length; i++) {
// eslint-disable-next-line no-loop-func
Object.keys(jsonData[i]).forEach(key => {
str += `${jsonData[i][key] + '\t'},`;
});
str += '\n';
}
console.log(str)
// str = '1,2,3,4,\n11,22,33,44,55,66,\na,b,c,d,\nhello' // \n 换行,也是excel换行。逗号则是代表一列
// encodeURIComponent解决中文乱码
const uri = `data:text/${filename.split('.').pop()};charset=utf-8,\ufeff${encodeURIComponent(str)}`;
console.log(uri)
// 通过创建a标签实现
let dom = document.createElement('a');
dom.download = filename;
dom.style.display = 'none';
dom.href = uri;
document.body.appendChild(dom);
dom.click();
setTimeout(() => {
document.body.removeChild(dom);
}, 1000);
}
const students = [{"学号":220101,"姓名":"细狗你","班级":1,"性别":"男","年龄":12},{"学号":220102,"姓名":"细鬼","班级":1,"性别":"男","年龄":11},{"学号":220103,"姓名":"渣渣辉","班级":1,"性别":"男","年龄":14},{"学号":220201,"姓名":"吴君如","班级":2,"性别":"女","年龄":12},{"学号":220202,"姓名":"苑琼丹","班级":2,"性别":"女","年龄":13},{"学号":220301,"姓名":"张三","班级":3,"性别":"男","年龄":13},{"学号":220302,"姓名":"王麻子","班级":3,"性别":"女","年龄":12},{"学号":220303,"姓名":"二狗子","班级":3,"性别":"男","年龄":12},{"学号":220304,"姓名":"李四","班级":3,"性别":"男","年龄":13},{"学号":220305,"姓名":"陈华春","班级":3,"性别":"女","年龄":14},{"学号":220306,"姓名":"赵丽华","班级":3,"性别":"女","年龄":12},{"学号":220401,"姓名":"坤哥","班级":4,"性别":"男","年龄":12},{"学号":220402,"姓名":"梁坤","班级":4,"性别":"男","年龄":12},{"学号":220403,"姓名":"梁晨","班级":4,"性别":"男","年龄":12},{"学号":220404,"姓名":"梅静","班级":4,"性别":"女","年龄":12},{"学号":220405,"姓名":"韩汉晨","班级":4,"性别":"男","年龄":13},{"学号":220406,"姓名":"凌楚峰","班级":4,"性别":"男","年龄":12}]
const examResults = [{"学号":220303,"姓名":"二狗子","语文":62,"数学":88,"随机排序":0.534449607369229},{"学号":220301,"姓名":"张三","语文":64,"数学":98,"随机排序":0.166291769352402},{"学号":220101,"姓名":"细狗你","语文":99,"数学":96,"随机排序":0.298748966878335},{"学号":220305,"姓名":"陈华春","语文":83,"数学":94,"随机排序":0.981885816605045},{"学号":220306,"姓名":"赵丽华","语文":87,"数学":97,"随机排序":0.777319924734964},{"学号":220405,"姓名":"韩汉晨","语文":63,"数学":100,"随机排序":0.0758610844747052},{"学号":220403,"姓名":"梁晨","语文":69,"数学":76,"随机排序":0.160749347477528},{"学号":220402,"姓名":"梁坤","语文":52,"数学":83,"随机排序":0.329833118669286},{"学号":220404,"姓名":"梅静","语文":43,"数学":100,"随机排序":0.844087333621201},{"学号":220302,"姓名":"王麻子","语文":67,"数学":66,"随机排序":0.376213770771804},{"学号":220401,"姓名":"坤哥","语文":100,"数学":97,"随机排序":0.736891795092198},{"学号":220304,"姓名":"李四","语文":47,"数学":59,"随机排序":0.801160817943515},{"学号":220406,"姓名":"凌楚峰","语文":55,"数学":98,"随机排序":0.0735291866946264}]
const testData = [
{ name: "George Washington", birthday: "1732-02-22" },
{ name: "John Adams", birthday: "1735-10-19" },
]
我有一个这样的哈希数组:[{:foo=>2,:date=>Sat,01Sep2014},{:foo2=>2,:date=>Sat,02Sep2014},{:foo3=>3,:date=>Sat,01Sep2014},{:foo4=>4,:date=>Sat,03Sep2014},{:foo5=>5,:date=>Sat,02Sep2014}]如果:date相同,我想合并哈希值。我对上面数组的期望是:[{:foo=>2,:foo3=>3,:date=>Sat,01Sep2014},{:foo2=>2,:foo5=>5:date=>Sat,02Sep2014},{:foo4=>4,:dat
我正在尝试用Prawn生成PDF。在我的PDF模板中,我有带单元格的表格。在其中一个单元格中,我有一个电子邮件地址:cell_email=pdf.make_cell(:content=>booking.user_email,:border_width=>0)我想让电子邮件链接到“mailto”链接。我知道我可以这样链接:pdf.formatted_text([{:text=>booking.user_email,:link=>"mailto:#{booking.user_email}"}])但是将这两行组合起来(将格式化文本作为内容)不起作用:cell_email=pdf.make_c
文章目录git常用命令(简介,详细参数往下看)Git提交代码步骤gitpullgitstatusgitaddgitcommitgitpushgit代码冲突合并问题方法一:放弃本地代码方法二:合并代码常用命令以及详细参数gitadd将文件添加到仓库:gitdiff比较文件异同gitlog查看历史记录gitreset代码回滚版本库相关操作远程仓库相关操作分支相关操作创建分支查看分支:gitbranch合并分支:gitmerge删除分支:gitbranch-ddev查看分支合并图:gitlog–graph–pretty=oneline–abbrev-commit撤消某次提交git用户名密码相关配置g
我正在尝试将一个简单的CSV文件读入HTML表格以在浏览器中显示,但我遇到了麻烦。这就是我正在尝试的:Controller:defshow@csv=CSV.open("file.csv",:headers=>true)end查看:输出:NameStartDateEndDateQuantityPostalCode基本上我只获取标题,而不会读取和呈现CSV正文。 最佳答案 这最终成为最终解决方案:Controller:defshow#OpenaCSVfile,andthenreaditintoaCSV::Tableobjectforda
有什么区别:@attr[:field]=new_value和@attr.merge(:field=>new_value) 最佳答案 如果您使用的是merge!而不是merge,则没有区别。唯一的区别是您可以在合并参数中使用多个字段(意思是:另一个散列)。例子:h1={"a"=>100,"b"=>200}h2={"b"=>254,"c"=>300}h3=h1.merge(h2)putsh1#=>{"a"=>100,"b"=>200}putsh3#=>{"a"=>100,"b"=>254,"c"=>300}h1.merge!(h2)pu
我想用Nokogiri解析HTML页面。页面的一部分有一个表,它没有使用任何特定的ID。是否可以提取如下内容:Today,3,455,34Today,1,1300,3664Today,10,100000,3444,Yesterday,3454,5656,3Yesterday,3545,1000,10Yesterday,3411,36223,15来自这个HTML:TodayYesterdayQntySizeLengthLengthSizeQnty345534345456563113003664354510001010100000344434113622315
我有可变数量的表格和可变数量的行,我想让它们一个接一个地显示,但如果表格不适合当前页面,请将其放在下一页,然后继续。我已将表格放入事务中,以便我可以回滚然后打印它(如果高度适合当前页面),但我如何获得表格高度?我现在有这段代码pdf.transactiondopdf.table@data,:font_size=>12,:border_style=>:grid,:horizontal_padding=>10,:vertical_padding=>3,:border_width=>2,:position=>:left,:row_colors=>["FFFFFF","DDDDDD"]pdf.
有没有办法快速将表格格式的ruby哈希打印到文件中?如:keyAkeyBkeyC...1232343451253474456...其中散列的值是不同大小的数组。还是使用双循环是唯一的方法?谢谢 最佳答案 试试我写的这个gem(在表中打印散列、ruby对象、ActiveRecord对象):http://github.com/arches/table_print 关于ruby-如何以表格格式快速打印Ruby哈希值?,我们在StackOverflow上找到一个类似的问题:
之前有人问过这个问题,我发现了以下clip关于如何一次设置一个类对象的所有属性,但由于批量分配保护,这在Rails中是不可能的。(例如,您不能Object.attributes={})有没有一种很好的方法可以将一个类的属性合并到另一个类中?object1.attributes=object2.attributes.inject({}){|h,(k,v)|h[k]=vifObjectModel.column_names.include?(k);h}谢谢。 最佳答案 利用assign_attributes使用:without_prote
我开始了一个新的Rails3.2.5项目,Assets管道不再工作了。CSS和Javascript文件不再编译。这是尝试生成Assets时日志的输出:StartedGET"/assets/application.css?body=1"for127.0.0.1at2012-06-1623:59:11-0700Servedasset/application.css-200OK(0ms)[2012-06-1623:59:11]ERRORNoMethodError:undefinedmethod`each'fornil:NilClass/Users/greg/.rbenv/versions/1