解决Excel文件密码格式化CSV问题的技巧

<!– wp:heading –> <h2 class=“wp-block-heading”>===INTRO:===</h2> <!– /wp:heading –><!– wp:paragraph –> CSV(Comma-Separated Values)文件是常用的数据存储格式之一。在使用Excel工具进行数据操作时,密码格式化CSV文件可能会导致无法打开或修改文件。本文提供了一些技巧,解决Excel文件密码格式化CSV问题。 <!– /wp:paragraph –><!– wp:heading –> <h2 class=“wp-block-heading”>===解决密码格式化CSV问题的方法===</h2> <!– /wp:heading –><!– wp:list {“ordered”:true} –> <!– wp:list-item –>1. 密码去除:在使用VBA代码去除密码时需要注意,密码不能为空。可以使用以下代码去除密码: <!– /wp:list-item –> <!– /wp:list –><!– wp:code –> <pre class=“wp-block-code”><code>Sub RemovePassword() Dim objFile As FileObject Dim strPath As String strPath = “C:UsersusernameDocumentsfile.csv” Set objFile = ThisWorkbook.FileObjects.Open(strPath) objFile.LockExcel = False objFile.CloseEnd Sub</code></pre> <!– /wp:code –><!– wp:list {“ordered”:true,“start”:2} –> <ol start=“2”><!– wp:list-item –><li>密码重置:如果您需要重置密码,可以使用以下代码:</li><!– /wp:list-item –></ol> ...

April 14, 2024 · 2 min · jiezi

关于excel:在vue中导出多sheet的方案-二

以前文章文章介绍了如何导出单列的excel本篇文章介绍下多sheet的excel的导出首先给大家看下成果 从上图可知,根底信息的数据格式和其余两个sheet不一样,所以要独自解决 依据现有的数据组装xlsx插件所需数据结构页面数据这里以我罕用数据为例 //根底数据个别是一个一般的对象 let valueObj = { registerNo: '', //洽购单号 statusName: '', //状态 submitDate: '', //提交工夫 //等等 } //第一个表格数据 const tableHeader = tableHeader: [ { title: "物料编码", map: "materialCode", }, { title: "物料类型", map: "materialTypeName", }, { title: "物料名称", map: "materialName", }, { title: "规格型号", map: "materialModel", }, ] const tableData = [ { materialCode: 'a', materialTypeName: 'b', materialName: 'b', materialModel: 'b', }, { materialCode: 'a', materialTypeName: 'b', materialName: 'b', materialModel: 'b', } ] //其余的表格数据同上 组装数据 let data = { title: "洽购单", //文件名称 baseSheetName: "根底信息", baseSheetData: [ { label: "洽购单号", map: "registerNo", value: "", }, { label: "以后状态", map: "registerStatusName", value: "", }, //等等 ], //寄存根底数据 list: [ { sheetName: '汇总', //第一个sheet数据 tableHeader: [ { title: "物料编码", map: "materialCode", }, { title: "物料类型", map: "materialTypeName", }, ], tableData: [ { materialCode: 'a', materialTypeName: 'b', materialName: 'b', materialModel: 'b', }, { materialCode: 'a', materialTypeName: 'b', materialName: 'b', materialModel: 'b', } ] }, { sheetName: '明细', tableHeader: [ //第二个sheet数据 { title: "物料编码", map: "materialCode", }, { title: "物料类型", map: "materialTypeName", }, { title: "物料名称", map: "materialName", }, { title: "规格型号", map: "materialModel", }, { title: "物料阐明", map: "materialIllustrate", }, ], tableData: [ { materialCode: 'a', materialTypeName: 'b', materialName: 'b', materialModel: 'b', }, { materialCode: 'a', materialTypeName: 'b', materialName: 'b', materialModel: 'b', } ] } ], //其余sheet数据 }导出函数封装import * as XLSX from "xlsx/xlsx.mjs"function exportExcel(data) { var wb = XLSX.utils.book_new() //解决根底数据 if (data.baseSheetName) { let baseDataArr = [] data.baseSheetData.map(item => { baseDataArr.push({ [data.title]: item.label, '': item.value }) }) let fdXslxws = XLSX.utils.json_to_sheet(baseDataArr) XLSX.utils.book_append_sheet(wb, fdXslxws, data.baseSheetName) } //解决其余表格数据 data.list.map((item, index) => { let arr = [] let newHeaderObj = {} item.tableHeader.map(item => { newHeaderObj[item.map] = item.title }) item.tableData.map((el, idx) => { let obj = {} for (let x in newHeaderObj) { obj[newHeaderObj[x]] = el[x] } arr.push(obj) }) let fdXslxws = XLSX.utils.json_to_sheet(arr) XLSX.utils.book_append_sheet(wb, fdXslxws, item.sheetName) }) XLSX.writeFile(wb, data.title + ".xlsx")}至此一个简略导出多列sheet的excel性能就实现了。。。 ...

February 29, 2024 · 2 min · jiezi

关于excel:Excelize-开源基础发布-281-版本2024-年首个更新

Excelize 是 Go 语言编写的用于操作电子表格办公文档的开源根底库,基于 ISO/IEC 29500、ECMA-376 国际标准。能够应用它来读取、写入由 Microsoft Excel、WPS、Apache OpenOffice、LibreOffice 等办公软件创立的电子表格文档。反对 XLAM / XLSM / XLSX / XLTM / XLTX 等多种文档格局,高度兼容带有款式、图片(表)、透视表、切片器等简单组件的文档,并提供流式读写反对,用于解决蕴含大规模数据的工作簿。可利用于各类报表平台、云计算、边缘计算等零碎。 开源代码GitHub: github.com/xuri/excelize 文档网站: xuri.me/excelize 2024年2月26日,社区正式公布了 2.8.1 版本,该版本蕴含了多项新增性能、谬误修复和兼容性晋升优化。上面是无关该版本更新内容的摘要,此版本中最显著的变动包含: 兼容性提醒降级至该版本须要您应用的 Go 语言为 1.18 或更高版本,以降级依赖库 golang.org/x/net将数据类型 HeaderFooterOptions 中的字段 AlignWithMargins 和 ScaleWithDoc 批改为指针类型移除了未应用的导出类型 ShapeColor新增性能新增函数 SetCellUint 反对设置无符号整型数新增函数 GetPictureCells 反对获取图片单元格坐标新增函数 GetConditionalStyle 反对获取条件格局款式定义新增函数 GetHeaderFooter 反对获取工作表页眉页脚控制字符设置新增函数 AddSlicer 反对为表格和数据透视表增加切片器新增函数 GetPivotTables 反对获取数据透视表新增函数 DeletePivotTable 反对删除数据透视表数据类型 PivotTableOptions 中增加了新的字段 Name 以反对创立数据透视表时指定自定义数据透视表名称新增 7 项公式函数:DBCS、SEARCH、SEARCHB、TEXT、TEXTAFTER、TEXTBEFORE 和 xlfn.ANCHORARRAY新增 ChartLineType 枚举类型,以反对设置图表区域边框线型数据类型 Chart 中增加了新的字段 Border 以反对设置图表区域边框类型数据类型 ChartLine 中增加了新的字段 Type 以反对设置图表线型新增文档对象关系部件名称与命名空间变量 NameSpaceSpreadSheetXR10、ContentTypeSlicer、ContentTypeSlicerCache 和 SourceRelationshipSlicer新增扩大资源标识常量 ExtURIPivotCacheDefinition容许在自定义名称、表格名称和数据透视表名称中应用点字符删除工作表中的表格时,将保留表格区域全副单元格的值反对读取带有分数数字格局的单元格删除图片时,如果图片仅有一处援用,将同时从工作簿外部删除对应的图片文件,以缩小生成工作簿的体积并打消由此产生的潜在平安危险反对为批注框设置自定义宽度和高度插入或删除行列时,反对更新条件格局、数据验证、自定义名称、图形对象、单元格公式、易失性函数中的单元格坐标援用新增 6 项新增条件格局类型:“特定文本”、“空值”、“无空值”、“谬误”、“无谬误”和“产生日期”公式计算引擎反对计算带有多重负号的单元格公式复制行时反对复制条件格局与数据验证设置行高度函数 SetRowHeight 反对通过指定行高度为 -1 移除自定义行高度设置当给定的行高度有效时,函数 SetRowHeight 将返回谬误提示信息增加图表函数 AddChart 反对设置图表中的数据标签地位增加图表函数 AddChart 反对设置图表区域、绘图区域和数据标记的填充色和通明填充,在 Chart、ChartPlotArea 和 ChartMarker 数据类型中增加了 Fill 选项增加图表函数 AddChart 反对设置图表坐标轴文字字体、字号和删除线格局数据类型 ChartSeries 中新增了 DataLabelPosition 字段,用于指定图表中各数据系列数据标签的地位数据类型 Chart 中新增了 BubbleSize 字段,用于设置气泡图和三维气泡图的气泡大小新增导出数据类型 ChartDataLabelPositionType获取图片单元格函数 GetPictureCells 和获取图片函数 GetPictures 反对读取由 Kingsoft WPS™ Office 创立的嵌入单元格图片设置条件格局函数 SetConditionalFormat 反对批量为多个单元格区域设置条件格局重命名工作表时反对更新自定义名称新增 GetBaseColor 函数,反对读取首选十六进制颜色代码公式计算引擎反对读取日期类型单元格的值单元格值读取函数反对继承应用 OpenReader 函数打开文档时所指定的 Options 选项设置兼容性晋升晋升了对外部带有绝对路径绘图部件工作簿的兼容性晋升了对外部带有浮点型 tabRatio 属性值工作簿部件的兼容性晋升了读取带有空的自定义数字格局单元格的兼容性晋升了与不反对默认主题部件命名空间电子表格预览程序的兼容性晋升了单元格批注形态与 KingSoft WPS™ Office 的兼容性保留工作簿时对外部部件进行排序,以确保在不扭转工作簿内容时生成的文件具备统一的哈希值问题修复增加对公式函数 MID 和 MIDB 中 num_chars 参数的查看,以防止出现正数导致的 panic修复局部状况下,公式函数 LEN、LOWER、PROPER、REPT、UPPER 和 IF 的计算结果为空的问题修复局部状况下,计算公式函数 CHITEST 和 MMULT 时呈现 panic 的问题修复 v2.8.0 中引入的问题,通过创立非凡自定义名称的形式设置打印区域和打印题目时不再返回谬误修复 v2.8.0 中引入的问题,修复了因为外部款式部件中索引色彩和 MRU 色彩缺省值解决有误导致的生成工作簿损坏问题修复 v2.8.0 中引入的问题,修复了特定状况下读取带有数字格局的单元格后果为空的问题修复 v2.7.1 中引入的问题,修复了气泡图和三维气泡图中不显示气泡的问题修复因外部工作表 ID 解决有误导致的特定状况下通过 AutoFilter 函数增加主动过滤器时呈现的 panic修复局部状况下在工作表中增加表格导致的工作表损坏问题修复局部状况下读取带有工夫类型数字格局单元格的值有误的问题反对计算字符型公式单元格的值修复在带有单元格表格的工作簿中增加表格时,表格 ID 生成有误的问题修复局部状况下工作簿内容关系部件失落的问题降级数字格局表达式解析器,以修复对于带有自定义文本的数字格局表达式格式化后果有误问题更新了简体中文和繁体中文语言的预设数字格局列表修复了局部状况下,自定义数字格局索引生成有误的问题修复通过删除后再增加表格形式更新表格区域范畴时呈现谬误的问题修复在应用流式读取函数后,所产生的临时文件无奈被清理的潜在问题修复局部状况下公式计算结果有误的问题修复并发读取单元格的值时呈现的竞态问题修复依据款式索引获取款式定义时,局部款式定义缺失问题修复局部状况下读取带有迷信记数法数字格局单元格的值后果有误的问题修复局部状况下,读取带有工作表中不含 r 属性的行元素导致的 panic 问题修复获取富文本单元格函数 GetCellRichText 在获取内联富文本时返回谬误的问题修复局部状况下,因为共享字符串表索引计算有误导致的设置单元格的值后果有误问题修复函数 GetConditionalFormats 读取带有“高于平均值”条件格局规定时 panic 的问题修复了删除行之后合并单元格有误的问题修复了 SetConditionalFormat 函数在创立带有多规定条件格局时,规定优先级有误的问题修复了 GetConditionalFormats 函数无奈读取带有突变填充格局数据条的问题修复了获取款式函数 GetStyle 或获取条件格局款式函数 GetConditionalStyle 所返回的小数位数 DecimalPlaces 字段值有误问题修复了应用 CalcCellValue 函数时,开启 RawCellValue 选项生效的问题性能优化进步了增加与删除数据透视表和图片的性能升高了修剪单元格时的内存占用其余Go Modules 依赖模块更新单元测试与文档更新蕴含简体中文、繁体中文、英语、法语、俄语、日语、韩语、阿拉伯语、德语和西班牙语的多国语言文档网站更新,新增葡萄牙语版本文档致谢感激 Excelize 的所有贡献者,以下是为此版本提交代码的贡献者列表: ...

February 26, 2024 · 2 min · jiezi

关于excel:excel-实现甘特图

应用excel,实现项目管理甘特图 演示 操作设置根本信息填入需要及对应工期抉择需要,跟进人,启动日期,将主动生成甘特图波及的VB代码Public Function GetArrayLength(arr As Variant) As Integer If IsEmpty(arr) Then GetArrayLength = 0 Else GetArrayLength = UBound(arr) - LBound(arr) + 1 End IfEnd FunctionPublic Function IsNull(val As Variant) As Boolean Dim result If val = "" Then result = True ElseIf IsEmpty(val) Then result = True Else result = False End If IsNull = resultEnd FunctionPublic Function IsWeekend(InputDate As Variant) As Boolean temp = CDate(InputDate) Select Case Weekday(temp) Case vbSaturday, vbSunday IsWeekend = True Case Else IsWeekend = False End SelectEnd FunctionPublic Function GetExceptCollection(r1 As range, r2 As range, Optional offset$ = 0) As Variant Dim arr1, arr2, arr3(), i&, row row = Application.ThisCell.row - offset arr1 = Application.Transpose(r1) arr2 = Application.Transpose(r2) Dim dict As Object Set dict = CreateObject("scripting.dictionary") For Each a In arr2 If Not IsNull(a) Then dict(a) = 1 End If Next ReDim arr3(GetArrayLength(arr1)) For Each a In arr1 If Not IsNull(a) And Not dict.exists(a) Then i = i + 1 arr3(i) = a End If Next If Not IsNull(arr3(row)) Then GetExceptCollection = arr3(row) Else GetExceptCollection = "" End IfEnd FunctionPublic Function GetEndDateByDuration(startDateV As Variant, durationI As Integer, holidaysR As range, workdaysR As range) As Date If IsNull(startDateV) Then GetEndDateByDuration = "" End If startDateD = CDate(startDateV) If Not IsDate(startDateD) Then GetEndDateByDuration = "" End If Dim holidaysA, workdaysA, holidaysD As Object, workdaysD As Object holidaysA = Application.Transpose(holidaysR) workdaysA = Application.Transpose(workdaysR) Set holidaysD = CreateObject("scripting.dictionary") For Each a In holidaysA temp = CDate(a) If Not IsNull(temp) Then holidaysD(temp) = 1 End If Next Set workdaysD = CreateObject("scripting.dictionary") For Each a In workdaysA temp = CDate(a) If Not IsNull(temp) Then workdaysD(temp) = 1 End If Next Dim actualDurationI As Integer, index As Integer Do While index < durationI temp = startDateD + actualDurationI If workdaysD.exists(temp) Then index = index + 1 ElseIf holidaysD.exists(temp) Then ElseIf IsWeekend(temp) Then Else index = index + 1 End If actualDurationI = actualDurationI + 1 Loop GetEndDateByDuration = startDateD + actualDurationI - 1 End FunctionExcel文件https://github.com/chencaize/fileRepo/blob/main/%E7%94%98%E7%89%B9%E5%9B%BE.xlsm ...

August 29, 2023 · 2 min · jiezi

关于excel:聊聊Excel解析如何处理百万行EXCEL文件-京东云技术团队

一、引言Excel表格在后盾管理系统中应用十分宽泛,多用来进行批量配置、数据导出工作。在日常开发中,咱们也免不了进行Excel数据处理。 那么,如何失当地解决数据量宏大的Excel文件,防止内存溢出问题?本文将比照剖析业界支流的Excel解析技术,并给出解决方案。 如果这是您第一次接触Excel解析,建议您从第二章理解本文根底概念;如果您曾经对POI有所理解,请跳转第三章浏览本文重点内容。 二、根底篇-POI说到Excel读写,就离不开这个圈子的的老大哥——POI。 Apache POI是一款Apache软件基金会用Java编写的收费开源的跨平台的 Java API,全称Poor Obfuscation Implementation,“简洁版的含糊实现”。它反对咱们用Java语言和包含Word、Excel、PowerPoint、Visio在内的所有Microsoft Office文档交互,进行数据读写和批改操作。 (1)“蹩脚”的电子表格在POI中,每种文档都有一个与之对应的文档格局,如97-2003版本的Excel文件(.xls),文档格局为HSSF——Horrible SpreadSheet Format,意为“蹩脚的电子表格格局”。尽管Apache风趣而虚心地将本人的API冠以“蹩脚”之名,不过这的确是一款全面而弱小的API。 以下是局部“蹩脚”的POI文档格局,包含Excel、Word等: Office文档对应POI格局Excel (.xls)HSSF (Horrible SpreadSheet Format)Word (.doc)HWPF (Horrible Word Processor Format)Visio (.vsd)HDGF (Horrible DiaGram Format)PowerPoint(.ppt)HSLF(Horrible Slide Layout Format)(2)OOXML简介微软在Office 2007版本推出了基于XML的技术规范:Office Open XML,简称OOXML。不同于老版本的二进制存储,在新标准下,所有Office文档都应用了XML格局书写,并应用ZIP格局进行压缩存储,大大晋升了规范性,也进步了压缩率,放大了文件体积,同时反对向后兼容。简略来说,OOXML定义了如何用一系列的XML文件来示意Office文档。 Xlsx文件的实质是XML让咱们看看一个采纳OOML规范的Xlsx文件的形成。咱们右键点击一个Xlsx文件,能够发现它能够被ZIP解压工具解压(或间接批改扩大名为.zip后解压),这阐明:Xlsx文件是用ZIP格局压缩的。解压后,能够看到如下目录格局: 关上其中的“/xl”目录,这是这个Excel的次要构造信息: 其中workbook.xml存储了整个Excel工作簿的构造,蕴含了几张sheet表单,而每张表单构造存储在/wooksheets文件夹中。styles.xml寄存单元格的格局信息,/theme文件夹寄存一些预约义的字体、色彩等数据。为了缩小压缩体积,表单中所有的字符数据被对立寄存在sharedStrings.xml中。通过剖析不难发现,Xlsx文件的主体数据都以XML格局书写。 XSSF格局为了反对新规范的Office文档,POI也推出了一套兼容OOXML规范的API,称作poi-ooxml。如Excel 2007文件(.xlsx)对应的POI文档格局为XSSF(XML SpreadSheet Format)。 以下是局部OOXML文档格局: Office文档对应POI格局Excel (.xlsx)XSSF (XML SpreadSheet Format)Word (.docx)XWPF (XML Word Processor Format)Visio (.vsdx)XDGF (XML DiaGram Format)PowerPoint (.pptx)XSLF (XML Slide Layout Format)(3)UserModel在POI中为咱们提供了两种解析Excel的模型,UserModel(用户模型)和EventModel(事件模型) 。两种解析模式都能够解决Excel文件,但解析形式、解决效率、内存占用量都不尽相同。最简略和实用的当属UserModel。 UserModel & DOM解析用户模型定义了如下接口: ...

July 3, 2023 · 5 min · jiezi

关于excel:Excel表格中出现E怎么办

置信很多人在应用Excel的时候都遇到过单元格变成###的状况,这是因为单元格列宽不够造成的,只须要减少列宽就能够失常显示。如果你在应用Excel的过程中遇到过呈现"E+"这种状况,此时不要惊恐,这是Excel主动对很大或很小的数字进行迷信计数法转换的后果,快来追随小编一起学习一下如何设置能够无效防止这种状况的产生吧! 小编在单元格中输出的数字是12345678910,此时输出的数字共计11位,能够看到单元格中呈现了E+格局,如下图: 这种状况下咱们能够通过减少列宽让数值失常显示,如下图: 小编在单元格中输出的数字是123456789101,此时输出的数字共计12位时,就会发现通过调整列宽的办法不能用了。 不要焦急,这是因为Excel零碎默认单元格中可能显示的最大数值为11位数,以下就是这种状况的解决办法: 咱们须要把输出的数值转成文本格式,扭转它的属性,这样无论你输出多少数字都是失常显示的。 1、点击须要扭转格局的单元格,右键抉择【设置单元格格局】,如图: 2、在【数字】中抉择【文本】,点击【确定】 3、此时就能够看到本人输出的数字残缺显示进去了。 在Excel中遇到数据被转换成迷信计数法的问题并不麻烦,只须要依照以上步骤更改单元格格局即可将其解决,心愿这些办法可能帮忙您更好地解决Excel表格中呈现E+的状况。欢送喜爱的敌人多多关注小编,为您带来更多Mac软件及教程。

June 15, 2023 · 1 min · jiezi

关于excel:使用phpofficephpspreadsheet实现加载excel模板生成excel

一:phpoffice/phpspreadsheet拓展装置composer require phpoffice/phpspreadsheet二:实现加载excel模板生成excel文件$spreadsheet = IOFactory::load('模板.xlsx');其余办法参考:php 应用phpoffice/phpspreadsheet拓展操作excel

April 27, 2023 · 1 min · jiezi

关于excel:电子表格软件与一站式BI的区别

看完本节内容,置信您可能理解到电子表格软件(代号电子表格软件)与「一站式 BI」的次要区别。所谓一站式BI在官网上的名称就是Smartbi V10.5,代号就是Smartbi始终在应用insight。 这两个产品都属于商业智能BI软件的品类,都是本地化部署,只是格调不同,就好比汽车行业的燃油车和新能源的区别,前者经久耐用,后者智能全面,用户能够依据本人的状况进行抉择。强调的是,如果估算不多,最好抉择前者,因为只有电子表格软件能够依照“订阅”形式洽购!  从Smartbi性能图谱看区别顾名思义,一站式BI的产品定位是“全面”,偏重的是现代化BI方面的“全面”,在报表性能上出于国产化趋势的思考更多偏向于Web电子表格,而不是基于Office的插件。下图是形容一站式BI的全功能图谱,电子表格软件与其重合的性能标注进去了。  对于一站式BI的介绍,可参见官网介绍,绝对于电子表格软件,其领有丰盛的内容资源,这里不再赘述。两者在性能上的差别Smartbi 电子表格软件尽管只是一站式BI中的局部性能,但曾经是具备齐备能力的BI报表工具,其最显著的个性就是利用了数据集和Office能力,而这两个个性在一站式BI中会逐渐淡化,被数据模型和Web电子表格所代替。对于还可能应用Windows的用户来说,电子表格软件就是多年来帮忙Smartbi建功立业的主打报表产品,这个报表性能曾经成为数千家企业用户的抉择。电子表格软件  与一站式 BI 的次要性能差别见下表:  从安装包的大小和复杂度上,两者也不再同一等级,电子表格软件只有1.13GB,而一站式BI达到2.81GB,启动后一站式BI对内存的需求量是电子表格软件的几倍。两者的非功能性差别电子表格软件 与一站式 BI 在产品定位、营销形式、价格与服务等方面也有很显示的差异,具体差别见下表:  如果你还想更具体的理解其差别,请与产品技术支持分割! 如果您对Smartbi电子表格软件感兴趣的话,能够点击链接收费申请试用:https://member.smartbi.com.cn/index/index/customerindex/form_...

April 18, 2023 · 1 min · jiezi

关于excel:电子表格软件能解决什么问题

在当下的时代,寰球经济十分沉闷,对于企业来说,经营的成绩须要“用数字谈话”——以数字来反映经营治理的的情况,这些都离不开报表,能够说报表的需要是无处不在的。 在企业所有的科技类我的项目中报表是最根本的性能。作为报表工程师、数据分析师、软件集成商或者作为企业外部的IT管理人员,如果你在施行一个企业报表我的项目、数据分析我的项目,做报表可能就是你的次要工作;如果你在施行一个ERP、CRM、OA等企业治理类我的项目,我的项目结项的要害很可能就是报表。  所以,对于企业来讲,大家都离不开报表。那什么是报表呢?通常有广义和狭义两种解读。 广义的报表通常指的是中国式报表。中国式报表是简单报表的代名词,它反映了具备特地列表头或行表头以及在行列交叉处实现自定义计算的报表。中国式报表的几个典型特色是格局简单、信息量大、表头乱。除此之外,中国式报表个别都是多数据源的,数据须要进行整合,还须要进行各种计算,有跨行式计算的,有无任何其余关系计算的,有统计汇总的,有统计数量的等等。 狭义的报表是一种通过表格、图表等模式来动态显示数据,并为使用者提供浏览、打印、导出和剖析性能的工具。报表的作用在于出现数字,数字出现的作用在于展现现状,明确与指标的差距,进而用于后续改善计划及行动计划的指南。狭义的报表当初更靠近蕴含了报表能力的数据分析与可视化的 BI(商业智能)。  在挪动互联的5G时代,手机上看报表也是必不可少的: Smartbi 电子表格软件是一款基于Excel/WPS进行报表开发的企业报表工具。它以“真Excel”为特色,将Excel及WPS表格作为报表设计器,灵便便捷地实现数据筹备、数据填报、报表开发、数据分析、公布分享等性能,不仅能全面满足各类中国式简单报表需要,还能极大水平升高开发门槛,显著进步报表开发和治理的效率! 同类的报表软件还有润乾、帆软,这3个产品在报表市场上是最相近的,也是多年的竞争对手,差异上只是电子表格软件采纳了Excel做报表设计器。 如果您是软件公司、修建企业的项目经理,将帮忙您超脱于 ERP、OA 等业务中,款式简略、性能无限的报表模块,充沛实现业务用户多变的报表需要。 如果您是零碎集成商、又或者是酒店行业的开发人员,将帮忙您疾速实现报表开发,及时实现高质量的报表设计,轻松实现报表与业务零碎的集成。 如果您是应用类 Excel 报表软件的 IT 公司与外贸企业的报表工程师,将帮忙您取得在原生 Excel/WPS 上间接开发报表的能力,无需额定学习即可马上实现。 如果您还在应用 Excel 来收集数据与设计报表,将帮忙您达成数据的标准采集,同时完满解决 Excel 在性能、平安、分享等方面存在的各种问题,无效提高效率。 古人云“工欲善其事、必先利其器”,报表软件与各种办公、通信工具一样,心愿升高客户在数据筹备、报表出现上破费的工夫。 如果您对Smartbi电子表格软件感兴趣的话,能够点击链接收费申请试用:https://member.smartbi.com.cn/index/index/customerindex/form_...

April 18, 2023 · 1 min · jiezi

关于excel:如何通过编程的方式获取工作表数量

“获取工作表数量”是一种 Excel 文件解决性能,用于确定指定 Excel 文件所蕴含的工作表数量。在读取或解决大量 Excel 文件时,理解文件中工作表的数量对于正确处理数据至关重要。此信息还可用于确定指标工作表名称或编号。该性能通常能够通过编程形式实现。上面我将分享如何应用 Java Excel 组件Free Spire.XLS for Java来获取工作表数量。 程序环境在进行操作之前,请先将jar导入到Java程序中,请参考以下两种导入办法:办法一:如果您应用的是 maven,能够通过增加以下代码到我的项目的 pom.xml 文件中,将 jar文件导入到应用程序中。 <repositories> <repository> <id>com.e-iceblue</id> <name>e-iceblue</name> <url>https://repo.e-iceblue.com/nexus/content/groups/public/</url> </repository></repositories><dependencies> <dependency> <groupId>e-iceblue</groupId> <artifactId>spire.xls.free</artifactId> <version>5.1.0</version> </dependency></dependencies>办法二:如果您没有应用 maven,则能够从此链接下载Free Spire.XLS for Java,找到lib文件夹下的Spire.XLS.jar并进行解压;而后在IDEA中创立一个新我的项目,顺次点击“文件”(File),“我的项目构造”(Project Structure),“组件”(Modules),“依赖项”(Dependencies),再点击右方绿色“+”下的第一个选项“jar文件或门路”(JARs or Directories),找到解压后的Spire.XLS.jar 文件,点击确认,将其导入到我的项目中。 具体步骤和代码创立Workbook实例。应用 Workbook.loadFromFile()办法加载示例文档。应用 Workbook.getWorksheets()办法获取工作表汇合,并应用 getCount()办法获取汇合中的工作表数。import com.spire.xls.Workbook;public class CountNumberOfWorsheets { public static void main(String[] args) { //创立Workbook实例 Workbook workbook = new Workbook(); //加载示例文档 workbook.loadFromFile("sample.xlsx"); //获取工作表数量 int sheetCount=workbook.getWorksheets().getCount(); //输入后果 System.out.println("The number of sheets is "+sheetCount); }} ...

March 17, 2023 · 1 min · jiezi

关于excel:前端js实现带样式的excelxlsx文件预览vue组件

都2023年了,怎么文件预览还这么难! 发现了问题之后,就想着能不能实现一个简略的VUE组件库,可能解决以上问题,让老手前端,可能十分高效的实现文件预览工作。 于是,我冀望开发一个vue-office组件库,它必须满足以下3个要求 应用肯定要简略,对老手要敌对,即传递一个文件地址,就可实现预览提供多种文件的一站式预览解决方案,解决常见的docx、excel、pdf三种文件的预览预览成果也好,不只是对内容预览,也要反对款式要求明确了,实现就绝对简略了,从github上筛选每个文档最优的预览计划,而后封装成VUE组件,然而坑还是十分多的,文章最初一部分介绍。 应用查看demo演示 github源码 装置有三个组件,能够别离依据须要进行装置 //docx文档预览组件npm install @vue-office/docx//excel文档预览组件npm install @vue-office/excel//pdf文档预览组件npm install @vue-office/pdf复制代码应用示例docx文档的预览<template> <vue-office-docx :src="docx" @rendered="rendered"/></template><script>//引入VueOfficeDocx组件import VueOfficeDocx from '@vue-office/docx'export default { components:{ VueOfficeDocx }, data(){ return { docx: 'http://static.shanhuxueyuan.com/test6.docx' //设置文档地址 } }, methods:{ rendered(){ console.log("渲染实现") } }}</script>复制代码excel文档预览<template> <vue-office-excel :src="excel" @rendered="rendered"/></template><script>//引入VueOfficeExcel组件import VueOfficeExcel from '@vue-office/excel'//引入相干款式import '@vue-office/excel/lib/index.css'export default { components:{ VueOfficeExcel }, data(){ return { excel: 'http://static.shanhuxueyuan.com/demo/excel.xlsx'//设置文档地址 } }, methods:{ rendered(){ console.log("渲染实现") } }}</script>复制代码pdf文档预览<template> <vue-office-pdf :src="pdf" @rendered="rendered"/></template><script>//引入VueOfficePdf组件import VueOfficePdf from '@vue-office/pdf'export default { components:{ VueOfficePdf }, data(){ return { pdf: 'http://static.shanhuxueyuan.com/test.pdf' //设置文档地址 } }, methods:{ rendered(){ console.log("渲染实现") } }}</script>复制代码整个应用形式非常简单,基本上给定文档的src地址,或者是上传文件的ArrayBuffer、Blob格局数据就可实现预览,具体办法见github中的介绍。 ...

February 17, 2023 · 1 min · jiezi

关于excel:使用-Excel-cdata-addin-连接-SAP-ABAP-系统时遇到错误消息

谬误音讯: Detail: NilHSBufInit: already initializedRFC_COMMUNICATION_FAILURE cdata 选项,没有填写 SAProuter 的中央,大略是哪里的问题? 笔者在 AG3 做 CRM 开发时,并没有手动保护 saprouter 的地址,如下图所示: 从蓝色高亮的 cdata 连贯保护界面里的 Connection Type 指定为 Netweaver 来看,依据 cdata 官网帮忙文档,这是默认值: Use NETWEAVER to indicate you are using the sapnwrfc.dll.应用 sapnwrfc.dll 提供的性能进行连贯。 试着点击 Advanced 看外面是否有容许保护 saprouter 信息的中央。 附录SAProuter 是一种软件应用程序,可在咱们的客户网络和 SAP 之间提供近程连贯。 SAProuter 可用于: 进步网络安全性,例如通过应用明码或仅容许来自已知起源的加密连贯管制和记录与 SAP 零碎的连贯当波及的程序因为网络配置而无奈互相通信时,设置间接连贯与广域网 (WAN) 通信时,通过缩小局域网 (LAN) 内的 SAP 零碎工作负载来进步性能和稳定性SAProuter 可与传统 SAP 产品以及剖析解决方案和收买一起应用。 无关哪些 SAP Business Analytics 产品受害于 SAProuter 连贯的残缺列表,请参阅 SAP Note 1478974。 ...

January 16, 2023 · 1 min · jiezi

关于excel:如何快速删除CSVExcelMarkdown表格的重复行

如果你正在应用 CSV、Excel 或 Markdown 表格,你可能会遇到反复行的问题。这可能是因为你手动输出了反复的数据,或者是因为你从其余源导入了反复的数据。无论起因是什么,删除反复行是一项重要的数据清理工作。本文将向你展现如何应用几种不同的办法来疾速删除 CSV、Excel 和 Markdown 表格中的反复行。 1. 在线表格工具【举荐】你能够应用一个名为 “Table Convert” 的 在线工具来删除反复行。这个工具能够帮忙你轻松地检查和删除 CSV、Excel、Markdown 表格中的反复行。只须要在浏览器关上 https://tableconvert.com/exce...,而后在数据源粘贴或上传要去重的内容,并点击 Table Editor 的 “Deduplicate” 按钮就能够轻松、疾速的实现去重,如图所示: 2.在 Excel 中删除反复行在 Excel 中删除反复行是一件非常简单的事。首先,关上你的 Excel 文件,而后抉择要查看反复行的列。接下来,点击“数据”菜单,抉择“删除反复项”。Excel 会弹出一个对话框,让你抉择要删除反复行的列。点击“确定”,Excel 就会删除所有反复行。 3.用 Python 删除 CSV 反复行如果你的数据存储在 CSV 文件中,你能够应用 Python 来删除反复行。首先,你须要装置 pandas 库。而后,应用以下代码来读取 CSV 文件并删除反复行: import pandas as pddata = pd.read_csv("your_file.csv")data = data.drop_duplicates()data.to_csv("your_file.csv", index=False)这段代码会读取 CSV 文件,删除反复行,并将清理后的数据写回到原文件中。 总结:删除 CSV、Excel 和 Markdown 表格中的反复行是一项重要的数据清理工作。通过应用上述办法,你能够轻松地查看并删除这些文件中的反复行,并确保你的数据是精确和有用的。

January 16, 2023 · 1 min · jiezi

关于excel:传播问卷调查数据不够自己生成假数据

问卷调查 Excel 款式 <button name="button" style="color: black">原文件下载</button> 生成代码序号间接 range 生成即可。 提交答卷工夫import timetime_str = time.strftime('%Y/%m/%d %H:%M:%S', time.localtime(time.time())) # 打印按指定格局排版的工夫print(time_str)所用工夫import randomprint(str(random.randint(80, 600)) + "秒")起源间接微信即可 起源详情间接 N/A 来自 IPfrom faker import Fakerfaker = Faker("zh-CN")template = "{ipv4}({province}-{city_name})"for i in range(100): r = template.format(ipv4=faker.ipv4(), province=faker.province(), city_name=faker.city_name()) print(r)Excel 头部生成间接选中 Excel 头部: 复制出如下: 1、您的性别: 2、您的年龄: 3、您的受教育水平: 4、您的工作是: 5、您是否是少数民族: 6、您的家庭是否有宗教信仰: 7、您试着理解过素食或尝试过素食: 8、(书籍、报纸、期刊) 8、(社交、互联网媒体) 8、(播送、电视) 8、(亲朋好友介绍) 9、平时您的素食类型: 10、您认为素食能够提供给身材足够的养分吗? 11、如果路过一家素食店,您会去品味吗? 12、您会成为一个素食主义者吗? 13、您认为素食主义者比那些非素食主义者更衰弱吗? 14、为了环保和衰弱,须要每周安顿一天吃素食,你是否能做到? 15、您感觉吃素对放弃衰弱和幸福有多重要? 16、您感觉吃素对升高碳排放、保护环境有多重要? 17、您对喝牛奶能补钙怎么看? 18、您是否认为肉类产品能够补充人体所需的大多数蛋白质成分 19、您认为女性在怀孕期间是否能够保持吃素吗? 20、您认为低脂纯素的饮食习惯是慢性疾病的终结者吗? 21、您有吃保健食品吗? 22、(预防疾病、促成衰弱) 22、(减肥塑身) 22、(进步静止或静止体现) 22、(加强免疫性能) 22、(进步记忆力或注意力) 22、(保护环境,爱护生灵) 22、(宗教信仰的影响) 22、(跟风随众) 22、(其余) 23、(家人敌人不了解、不认可或拥护) 23、(每天不晓得吃什么) 23、(外出就餐找不到适合的餐厅) 23、(超市和市场里可抉择食材太少) 23、(不懂得如何进行养分搭配) 23、(不晓得如何烹饪) 23、(聚餐时比拟难堪,因为其他人吃肉) 23、(单位食堂或外卖很难找到适合的饭菜) 24、(家人敌人的认可和了解) 24、(把握更多烹饪技巧,让食物变得美味和丰盛) 24、(须要学习更多营养学及中西医常识) 24、(能买到更多素食专属产品) 24、(其余) 总分改写成 Python 字符串并生成指标数据: ...

August 22, 2022 · 8 min · jiezi

关于excel:基于-xlsxstyle-的前端合并单元格复杂表头导出

我的项目性能任意层级合并单元格简单表头导出 表头与数据项间接映射,无需保护 Excel 索引项匹配关系 主动计算、生成表头合并单元格配置信息 在线示例步骤零:如需疾速测试,可点击顶部的示例按钮,可疾速填充各层级合并单元格 Excel 测试数据 步骤一:输出测试数据源,即从后端获取的数据数组。步骤二:输出「Excel 表头构造字符串」与「指标数据结构 key」之间的映射关系数组 "key" 为 Excel 表头,每一列的所处层级关系。如「根底信息.年龄」对应的就是 Excel 表在第二列中的关系,第一级是「根底信息」,第二级是「年龄」 "value" 为数据源数据结构的层级关系。「baseInfo.age」的意思是,将数据源中 baseInfo.age 这个属性的值,设置到 Excel 表的第二列中。 【特地留神一】数组的程序,即为 Excel 表头的程序。第 N - 1 索引项的配置,即为 Excel 中第 N 列的菜单配置 【特地留神二】Excel 表的层级映射关系与指标对象的层级映射关系,没有强制束缚和要求。如Excel 中的 "手机号",只有一层构造,但齐全能够转化为指标对象中的 "contact.phone" 二级构造。反之亦然。 步骤三:点击「导出 Excel」按钮,即可实现数据 Excel 文件导出。解析后的页面介绍 左侧区域为数据源转化为 Excel 数据后,每个单元格的数据。包含顶部表头数据,及具体数据行。右侧区域为 Excel 表头数据的合并单元格配置项。利用该配置数据,能够通过「xlsx-style」库实现对表头的单元格合并。具体函数应用形式示例遵循起码常识准则,我的项目中的 core.js 文件,即为转换函数所在文件。外面一共不到 200 行代码。能够间接粘贴复制到所需我的项目外面。 示例间接应用的 script 文件整体引入的形式。所以迁徙到基于 npm 的我的项目中时,须要将 core.js 中的 ‘Window.XLS.write’ 全局变量应用形式,改为通过 import { write } from 'xlsx' 的应用形式。如果本我的项目的确有帮忙到小伙伴,小伙伴有需要的话,能够在 github 中提 issues,有需要的话,将补充基于 npm 的版本,以及带上 ts 类型束缚的版本。全副外围源码/** * 将数据源,转化为 Excel 单元格数据,并生成 Excel 表头 * @param dataList 数据源 * @param textKeyMaps // Excel 中文表头层级与数据源英文层级间的映射表 * @param headerFirstRow // 表头首行所在行,为了兼容表格顶部还插入有其余 Excel 行的状况,即表格不在首行 * @returns { headerMerges, // 表头合并单元格配置项 cells, // 表头及数据项的 Excel 单元格数组 } */function transformDataToSheetCells(dataList, textKeyMaps, headerFirstRow = 0) { // 获取从 textKeyMaps 解析,拆分后的,中英文 keys 数组 function getKeysList(textKeyMaps) { const chineseKeysList = [] const englishKeysList = [] textKeyMaps.forEach(textKeyMap => { const keyStr = Object.values(textKeyMap)[0] const textStr = Object.keys(textKeyMap)[0] englishKeysList.push(keyStr.split('.')) chineseKeysList.push(textStr.split('.')) }) return { englishKeysList, chineseKeysList } } // 获取表头行数 function getHeaderRowNum(chineseKeysList) { let maxLevel = 1 chineseKeysList.forEach(chineseKeys => { maxLevel = Math.max(chineseKeys.length, maxLevel) }) return maxLevel } // 获取表头行 cell 数据 function getHeaderRows(headerRowNum, chineseKeysList) { const headerRows = [] // 初始化,全副设置为 '' for (let rowIndex = 0; rowIndex < headerRowNum; rowIndex++) { const row = new Array(chineseKeysList.length).fill('') headerRows.push(row) } // 将表头 cell 设置为对应的中文 chineseKeysList.forEach((chineseKeys, colIndex) => { for (let rowIndex = 0; rowIndex < chineseKeys.length; rowIndex++) { headerRows[rowIndex][colIndex] = chineseKeys[rowIndex] } }) // 去除须要合并单元格的每一列中。反复的 cell 数据,反复的,则设置为 '' headerRows.forEach(headerRow => { let lastColValue = '' headerRow.forEach((cell, colIndex) => { if (lastColValue !== cell) { lastColValue = cell } else { headerRow[colIndex] = '' } }) }) return headerRows } // 获取合并单元格配置 function getMerges(headerRowNum, chineseKeysList) { const merges = [] // 竖向合并 chineseKeysList.forEach((chineseKeys, colIndex) => { // 当前列,每一行都有数据,这无须要竖向合并 if (chineseKeys.length === headerRowNum) { return } // 否则。存在数据须要竖向合并,竖向合并的行数,即为比最高行数少的行数 merges.push({ s: { r: chineseKeys.length - 1 + headerFirstRow, c: colIndex, }, e: { r: headerRowNum - 1 + headerFirstRow, c: colIndex, } }) }) // 横向合并 for (let rowIndex = 0; rowIndex < headerRowNum; rowIndex++) { const rowCells = chineseKeysList.map(chineseKeys => chineseKeys[rowIndex]) let preCell = '' // 前一个单元格 let merge = null // 以后合并配置项 rowCells.forEach((cell, colIndex) => { if (preCell === cell) { // 如果二者雷同,则证实须要横向合并单元格 if (!merge) { // merge 不存在,则创立, merge = { s: { r: rowIndex + headerFirstRow, c: colIndex - 1 }, e: { r: rowIndex + headerFirstRow, c: colIndex } } merges.push(merge) // 增加一个合并对象 } else { merge.e.c = colIndex // 批改其合并完结列 } } else { preCell = cell merge = null } }) } return merges } // 获取转化数据结构为 Excel 数据行 function getDataRows(dataList) { const dataRows = [] dataList.forEach(dataItem => { const cells = [] englishKeysList.forEach(keyLevel => { const value = keyLevel.reduce((dataItem, key) => dataItem[key] || '', dataItem).toString() cells.push(value) }) dataRows.push(cells) }) return dataRows } const { englishKeysList, chineseKeysList } = getKeysList(textKeyMaps) const headerRowNum = getHeaderRowNum(chineseKeysList) const headerMerges = getMerges(headerRowNum, chineseKeysList) const headerRows = getHeaderRows(headerRowNum, chineseKeysList) const dataRows = getDataRows(dataList) return { headerMerges, cells: [...headerRows, ...dataRows], }}/** * 导出为携带款式的 xlsx 文件 * @param {*} param * @param param.filename 导出的文件名 * @param param.worksheet 导出的 sheet 数据 */function toStyleXlsx({ filename, worksheet }) { const workbook = { SheetNames: [filename], Sheets: { [filename]: worksheet, }, } // writeFile(workbook, filename, { bookType: 'xlsx' }) let wopts = { bookType: 'xlsx', bookSST: false, type: 'binary' } let wbout = window.XLS.write(workbook, wopts) // 应用xlsx-style 写入 function s2ab(s) { let buf = new ArrayBuffer(s.length) let view = new Uint8Array(buf) for (let i = 0; i !== s.length; ++i) { // eslint-disable-next-line no-bitwise view[i] = s.charCodeAt(i) & 0xFF } return buf } saveAs(new Blob([s2ab(wbout)], { type: '' }), filename)}这里还有 Excel 合并单元格简单表头导入解析示例 ...

August 19, 2022 · 3 min · jiezi

关于excel:基于-SheetJS-的前端合并单元格复杂表头导入

我的项目性能任意层级合并单元格简单表头解析主动转化为指标层级的数据结构主动生成基于 antdv 的 table 列配置数据 columns 及对于数据源 dataSource。在页面端复现 Excel 成果。在线测试示例步骤零:如需疾速测试,可点击顶部的示例按钮,可疾速填充测试数据,并主动下载对应的 Excel 文件,点击上传 Excel 文件即可复现整个应用流程步骤一:输出「Excel 表头构造字符串」与「指标数据结构 key」之间的映射关系 "key" 为 Excel 表头,每一列的所处层级关系。如「根底信息.年龄」对应的就是 Excel 表在第二列中的关系,第一级是「根底信息」,第二级是「年龄」"value" 为须要转换的指标数据结构的层级关系。「baseInfo.age」的意思是,将 Excel 表第二行的数据,转化为指标对象中.baseInfo.age 这个属性。【特地留神一】"key":"value" 的映射关系,没有程序的要求,无须要按 Excel 表的每一列的数据进行排序。【特地留神二】Excel 表的层级映射关系与指标对象的层级映射关系,没有强制束缚和要求。如Excel 中的 "手机号",只有一层构造,但齐全能够转化为指标对象中的 "contact.phone" 二级构造。反之亦然。步骤二:点击右侧,上传对应的 Excel 文件,即可实现 Excel 解析。解析后的页面介绍 顶部为基于 antdv 的 table 组件的复现成果。复现 Excel 表格中,合并完单元格后的成果。 table 组件用到的 columns 配置,及 dataSource 数据,均由解析函数一并返回。无须要开发者二次开发及保护。底部为解析函数解析后返回的三个数据后果。别离为 解析后的 antdv columns 表格列的配置项,间接传递给 table 组件的 columns 属性应用。解析后的 antdv dataSource 表格数据源,间接传递给 table 组件的 data-source 属性应用。解析后的指标数据结构数组。即依据步骤一设置的映射表,将 Excel 各个单元格数据,转换后的指标数据结构。个别状况下,该数据结构,即为传递给后端的数据结构。背景,解决什么问题间接应用 SheetJS 的 XLSX.utils.sheet_to_json 函数进行 excel 数据转化时,仅反对一行表头的 Excel 表格数据解析(只辨认 Excel 内容的第一行作为题目),无奈辨认表头进行过合并单元格的 Excel 数据解析sheet_to_json 转化的 JSON 数据,是以中文为 key 的对象,不合乎编程习惯,须要开发者手动进行数据中英文 key 转换,自行转换为指标数据结构。excel 表头的组织与复现,进行 Excel 表上传时,通常须要在前端展示表格内容,给用户须要数据复现及确认。这个过程须要开发者手动组织实现。起码常识准则,提供最小化 demo 示例,没有脚手架,无须要装置 npm 依赖包。纯 html + js 文件。疾速测试代码可行性。边改边测进行二次开发。具体函数应用形式示例遵循起码常识准则,我的项目中的 core.js 文件,即为转换函数所在文件。外面一共不到 200 行代码。能够间接粘贴复制到所需我的项目外面。示例间接应用的 script 文件整体引入的形式。所以迁徙到基于 npm 的我的项目中时,须要将 core.js 中的 ‘XLSX.utils’ 全局变量应用形式,改为通过 import { utils } from 'xlsx' 的应用形式。如果本我的项目的确有帮忙到小伙伴,小伙伴有需要的话,能够在 github 中提 issues,有需要的话,将补充基于 npm 的版本,以及带上 ts 类型束缚的版本。转换函数运行逻辑获取 Excel 所有单元格数据 ...

August 19, 2022 · 6 min · jiezi

关于excel:身份证号‘去除

C1单元格写入公式=SUBSTITUTE(B1,"'","")或=SUBSTITUTE(B1,"'",)下拉复制公式或双击填充柄实现后选中C列---右键---选择性粘贴----数值---确定---再选中C列---右键----设置单元格格局---数字选项卡---文本---确定后删去B列---新的B列就是你要的数据款式

August 18, 2022 · 1 min · jiezi

关于excel:方法一键批量把联系人号码添加导入WhatsApp通讯录

做外贸的敌人常常要用到的即时通讯工具就是WhatsApp,你是否还在手动一个个将联系人增加到WhatsApp通讯录?如果你感觉手动输出太麻烦,那你找对中央了,上面具体解说如何把联系人号码一键批量导入到iPhone苹果手机和Android安卓手机的通讯录里。无论你应用的是iPhone苹果手机还是Android安卓手机,向WhatsApp增加联系人的过程都是一样的。一个关键性的难题:因为你要存入的是国外号码,不能应用任何前缀“0” 或完结代码。要用“+”号作开首,再输出帼稼和地区代码(这个你在网上本人查),最初再输出电话号码。如果号码后面没有加“+”号和帼稼地区代码,那么你关上WhatsApp是无奈辨认对方号码的。然而问题来了,excel表格又没法输出“+”加号,即便你输出了excel表格会认为是一个公式,不会显示“+”的。那有没有好的解决办法呢?当然有:金芝号码提取导入助手,在软件的倒数第二个功能模块叫“号码前加字符”,能够帮你在号码背后批量增加入任意的字符,并且能够导出txt格局。比方你输出“+001145”,那就是下图的这样,操作简略方便快捷。第1步:后面说了如何批量给号码后面退出“+”加号和代码了,那就能够筹备好正确格局的号码了,接下来你把人铭和号码别离复制粘贴好,放入软件的第一个框和第二个框,见下图。 第2步:在软件“金芝号码提取导入助手”上,点下方的“生成通讯录”,那么你将失去一个通讯录文件,你通过电脑徽xin或电脑q,把这个文件发给你的手机徽xin或手机q,再到手机上关上这个文件。留神,这个文件是手机上关上的,不是电脑上关上的。第3步:你在手机上关上电脑上发送过去的文件,抉择“其余利用形式关上”,抉择“通讯录”、“电括本”、“拨号与分割”等选项,即可主动导入手机通讯录。倡议通过电脑徽xin或q发给手机的形式导入。当然你没有后面这两个的话,本人想方法把“通讯录文件”,发送到手机上。手机保留好文件后,进入手机【设置】-【分割】-【导入/导出分割】-【从存储设备导入】,手机会自动识别方才的通讯录文件,抉择咱们刚刚保留的文件并确认,就能够开始导入了。保留好的样子见下图。默认状况下,WhatsApp会主动同步手机中存储的联系人,并查看他们是否有WhatsApp。导入实现后刷新一下再登录WhatsApp就会主动显示对方的WhatsApp了,如果对方号码有开明了WhatsApp,你就能够间接给对方发WhatsApp悄息了。当然了,后面说的办法:如何批量把联系人号码增加导入WhatsApp通讯录里,软件只负责批量帮你增加存入号码,不负责前面的显示不显示对方的问题,那是你的本人app显示的反馈快慢,须要工夫和过程,跟导入的软件没有关系。

August 13, 2022 · 1 min · jiezi

关于excel:xsheet-开发入门教程自定义初始化配置

x-sheet 开发教程:外围 API 的应用x-sheet 开发教程:如何二次开发 介绍x-sheet 是一款高性能 Web JavaScript Canvas 电子表格,之前小编写过一篇 x-sheet 入门体验,简略介绍了一下如何应用 x-sheet。这次咱们持续深刻一下,理解下 x-sheet 还反对哪些配置,通过批改配置能够自定义咱们的表格布局和个性。 最新原文 X-Sheet 开发教程:初始化配置自定义布局 配置小编在应用 x-sheet 过程中,总结出了一份绝对比拟全的配置清单,能够参考下。 const settings = { // 工作簿配置 workConfig: { // 创立工夫 created: "", // 批改工夫 modified: "", // 作者信息 creator: "", // 最初批改作者 lastModifiedBy: "", // 工作簿名称 name: "x-sheet", // 顶部配置 top: { // 顶部选项栏配置 option: { // 是否显示选项栏 show: true, }, // 顶部菜单栏配置 menu: { // 是否显示菜单栏 show: true, }, }, // 主体配置 body: { // 工作表菜单配置 sheetConfig: { // 是否显示右击菜单 showMenu: true, }, // 工作表主体配置 sheets: [ { // 工作表名称 name: "sheet1", // 表格配置 tableConfig: { // 题目行列配置 index: { // 题目行高度 height: 30, // 题目列宽度 width: 50, // 题目行列边框色彩 gridColor: "rgb(193,193,193)", // 题目行列字体大小 size: 12, // 题目行列字体色彩 color: "rgb(0,0,0)", }, // 表格整体配置 table: { // 是否显示网格线 showGrid: true, // 表格区域背景色彩 background: "rgb(255,255,255)", // 网格线色彩 gridColor: "rgb(225,225,225)", }, // 行配置 rows: { // 自定义最大行数 len: 100, // 默认行高 height: 30, // 行配置数据 data: [ { // 自定义行高,未设置的会取默认行高 height: 100 }, ], }, // 列配置 cols: { // 自定义最大列数 len: 25, // 默认列宽 width: 110, // 行配置数据 data: [{ // 自定义列宽,未设置的会取默认列宽 width: 200 }], }, // 解冻范畴 xFixedView: { // 解冻列索引,-1为不解冻 fxLeft: -1, // 解冻行索引,-1为不解冻 fxTop: -1, }, // 解冻分割线款式 xFixedBar: { // 解冻行分割线高度 height: 16, // 解冻列分割线宽度 width: 26, // 解冻分割线背景色 background: "rgb(234,234,234)", // 解冻分割线按钮背景色 buttonColor: "rgb(193,193,193)", }, // 表格数据,二维数组 data: [ [ // A1 单元格数据 { // 单元格类型 contentType: 2, // 字体属性 fontAttr: { // 换行 textWrap: 2, // 方向 direction: "vertical", }, // 富文本配置 richText: { // 富文本具体字段信息 rich: [ // 第一个段富文本 { // 字体 name: "Arial", // 字体大小 size: 14, // 文本内容 text: "我是", // 字体色彩 color: "rgb(255,0,2)", // 是否加粗 bold: false, // 是否斜体 italic: false, // 是否有删除线 strikethrough: false, // 是否有下划线 underline: false, }, { // 第二段富文本蕴含的字符 // 如果没有配置款式,就取单元格的款式,单元格也没有设置款式,就取默认的款式 text: "富文本", }, ], }, }, { // 背景色彩 background: "rgb(255,255,0)", // 单元格图标 icons: [], // 自定义属性 custom: {}, // 字体测量尺子 ruler: undefined, // 格式化类型 format: "default", // 单元格公式 formula: undefined, // 文本内容 text: "Text", // 格式化后的内容 formatText: "Text", // 内容的宽度 contentWidth: 100, // 内容的高度 contentHeight: 100, // 字体属性 fontAttr: { // 字体 name: "Arial", // 字体大小 size: 14, // 字体色彩 color: "rgb(0,0,0)", // 是否加粗 bold: false, // 是否斜体 italic: false, // 是否有删除线 strikethrough: false, // 是否有下划线 underline: false, // 内边距 padding: 5, // 文本角度 angle: 0, // 文本方向 direction: "horizontal", // 'horizontal' 'vertical' 'angle' 'bar' // 程度对齐形式 align: "left", // 'left' 'center' 'right' // 垂直对齐形式 verticalAlign: "middle", // 'top' 'middle' 'bottom' // 主动换行 textWrap: 1, // 1 溢出 2 换行 3 截断 }, // 边框属性 borderAttr: { // 左边框 left: { // 层级 zIndex: 0, // 是否显示 display: true, // 宽度类型 widthType: "low", // 'low' 'medium' 'high' // 色彩 color: "rgb(0,0,0)", // 线条类型 type: 0, // 0 solid 1 dotted 2 point 3 double }, // 左边框 right: { zIndex: 0, display: true, widthType: "medium", color: "rgb(0,255,0)", type: 0, }, // 上边框 top: { zIndex: 0, display: false, widthType: "high", color: "rgb(0,0,255)", type: 0, }, // 下边框 bottom: { zIndex: 0, display: true, widthType: "high", color: "rgb(0,255,255)", type: 3, }, }, }, ], ], // 爱护配置 protection: { protections: [], }, // 是否爱护 sheetProtection: true, // 合并单元格 merge: { merges: ["A2:B3", "D5:H9"] }, }, }, ], // 工作表选项卡配置 tabConfig: { // 是否显示选项卡右击菜单 showMenu: true, }, }, // 底部状态栏配置 bottom: { // 是否显示状态栏 show: true, }, }, }; // 初始化x-sheet new XSheet("#demo1", settings);总结x-sheet 目前还在开发中,局部 API 还不稳固,后续有变动小编会及时更新。 ...

July 27, 2022 · 3 min · jiezi

关于excel:前端导出-excel基于-Blobjs-和-Export2Exceljs-做前端导出

装置依赖 npm install -S file-savernpm install -S xlsxnpm install -D script-loader 也能够应用 cnpm 装置,在此辨别一下 npm -i 与 npm install -s 与 - d 的区别npm i module_name -g 全局装置,i 是 install 的简写-S 就是–save 的简写-D 就是–save-dev 这样装置的包的名称及版本号就会存在 package.json 的 devDependencies 这个外面,而–save 会将包的名称及版本号放在 dependencies 外面。 咱们在应用 npm install 装置模块或插件的时候,有两种命令把他们写入到 package.json 文件外面去,比方: –save-dev–save在 package.json 文件外面提现进去的区别就是,应用 --save-dev 装置的 插件,被写入到 devDependencies 对象外面去,而应用 --save 装置的插件,是被写入到 dependencies 对象外面去。那么 package.json 文件外面的 devDependencies 和 dependencies 对象有什么区别呢? devDependencies 外面的插件只用于开发环境,不用于生产环境,而 dependencies 是须要公布到生产环境的。 ...

June 6, 2022 · 7 min · jiezi

关于excel:XSpreadsheet-设置默认数据默认样式

文档 文档中没写数据格式是什么样的,上面的代码是这个我的项目示例的默认数据 <script>const rows10 = { len: 1000 }for (let i = 0; i < 1000; i += 1) { rows10[i] = { cells: { 0: { text: 'A-' + i }, 1: { text: 'B-' + i }, 2: { text: 'C-' + i }, 3: { text: 'D-' + i }, 4: { text: 'E-' + i }, 5: { text: 'F-' + i }, }, }}const rows = { len: 80, 1: { cells: { 0: { text: 'testingtesttestetst' }, 2: { text: 'testing' }, }, }, 2: { cells: { 0: { text: 'render', style: 0 }, 1: { text: 'Hello' }, 2: { text: 'haha', merge: [1, 1] }, }, }, 8: { cells: { 8: { text: 'border test', style: 0 }, }, },}const data = [{ freeze: 'B3', styles: [ { bgcolor: '#f4f5f8', textwrap: true, color: '#900b09', border: { top: ['thin', '#0366d6'], bottom: ['thin', '#0366d6'], right: ['thin', '#0366d6'], left: ['thin', '#0366d6'], }, }, ], merges: ['C3:D4'], cols: { len: 10, 2: { width: 200 }, }, name: '123', rows,},{ name: 'sheet-test', rows: rows10 },]到这一步,根本的数据曾经配置实现了。在应用的过程中须要更改整个背景色,网格线色彩等款式文档配置中并不反对这些配置。在github把源码下载下来 ...

March 18, 2022 · 2 min · jiezi

关于excel:python操作excel查找数据并移动到新表

思路:1、操作本地excel获取数据;2、对数据进行操作并存储(看是否去重)3、将解决后的数据写入新表操作:1、操作本地excel获取数据: 前面增加新表的时候,须要增加上面几个步骤,来保障找到反复数据之后的解决: 原表: 最终后果:外面有个关键点,就是openpyxl,实用于只实用于新版的xlsx,如果用其余格局会报错。 原文为此文章: https://mp.weixin.qq.com/s?__...本人尝试外面的操作并不能满足理论需要,须要另做批改。

January 27, 2022 · 1 min · jiezi

关于excel:Execel学习第3讲-查找替换与定位

查找、替换与定位查找与替换查找快捷键:ctrl+F替换 (替换快捷键:ctrl+H) 格局替换:选项-单元格匹配,格局(能够辨认单元格的任一格局即可,从单元格中辨认格局)含糊查找:查找张(通配符:示意任何多个值);张?(英文状态?号)示意一个字(留神单元格匹配);本来就带?的内容,查找张~*(~让前面的字符不失效)。撤销:ctrl+Z定位工具通过名称框(左上角)定位单元格区域地位 A10000 回车A9000:B10000 回车 (选中A9000到B10000)9000:10000 回车(9000行到10000行)定义名称 选中区域,在名称框定义。(罕用区域)(取名尽量中文、单词)查找与替换-转到-援用地位,定位条件 批注(单元格右上角红三角) 选中单元格-右键-插入批注 右键-显示/暗藏批注/编辑批注。 审阅选项卡-显示所有批注。 批注的文本框形态:选中单元格-显示批注;插入-形态-绘图工具中格局-编辑形态-更改形态右键- 增加到快速访问工具栏;单元格右键-编辑批注 -选中批注边框-而后更改形态。 批注加图片:选中单元格右键-编辑批注-右键批注边框-设置批注格局-色彩与线条-填充成果选图 片。把有批注的单元格设置为红色填充:查找与替换-转到-定位条件-批注-确定-更改背景填充色(小桶形态)。为有公式的单元格设置红色填充:查找与替换-定位条件-公式-确定-颜料桶填充色彩。填充解除单元格合并后遗留的空白单元格: 勾销单元格合并:选中合并的单元格-合并后居中-再填充变空的单元格。(如何批量填充防止重 复?) 选中一个区域-其中一个单元格填值-ctrl+enter,则区域内所有单元格都为该值。 选中区域-定位条件-空值-确定-=向上箭头-ctrl+enter。批量删除图片: 网页数据拷到excel会带过去很多图片,查找和抉择-定位条件-对象-确定-delete。 查找与替换-选择对象-抉择图片。

January 20, 2022 · 1 min · jiezi

关于excel:活用Excel成为真正的全战工程师

因为工作的关系,大部分程序员都比拟少接触Excel,一旦遇到和Excel相干的问题可能第一反馈是用code解决。其实,如果数据曾经在Excel外面,是能够很容易用Excel自身的性能解决的。另外,如果相熟Excel的公式构造,有些场景下还能够借助Excel来批量创立程序代码。本文用几个案例来向大家展现这方面的技巧。 Excel 这个电子表格软件的主力用户群体是财务、HR 以及各部门须要解决和剖析数据的信息工作者。因为工作的关系,我和表哥表姐表弟表妹打的交道很多。于是我常常听到他们的吐槽: “咱们公司的IT连VLOOKUP都不会”“我就想把二维表转一维表,我BF竟然说要等他有空敲代码才行” 在他们的心里,业余CS出身的程序员们应该是通吃所有软件问题的,包含且不限于Excel。 但这显著属于误会,因为大部分程序员平时工作中与 Excel 很少有交加,不会 VLOOKUP而且凡事都想撸代码解决是失常景象。程序员是信息时代的王者,所谓没有什么事件是一行代码搞不定的,如果不行,那就再写几行。 我也有很多程序猿和攻城狮敌人,偶然会帮他们解决 Excel 方面的小问题。我始终有一个观点,任何人这辈子都肯定会遇上 Excel,提前略微理解一下,点亮这棵技能树,是很有价值的。况且,对于有深厚功底的程序员来说,学 Excel 的速度必定是普通人的10倍。上面,我就用几个例子来分享一下,哪怕是程序员也能够借助 Excel 进步拔剑的速度! 拼接 SQL 条件语句 比方业务部门冷不丁发给你一张表格,让你在后盾把这些数据处理一下。 这是个长期工作,你须要写一条SQL语句,无论是 UPDATE 还是 DELETE,都须要条件语句,这几十个数据怎么疾速写成条件语句呢? 先说重点:如果数据曾经在 Excel 外面了,你要深信 Excel 就是最有方法最省力的工具。 咱们能够在B2写入公式: =B1&","&"'"&A2&"'"双击B2右下角的填充柄,主动复制公式到整列。 最初间接复制B25单元格,粘贴到你的SQL编辑器外面,略微编辑一下,就功败垂成啦。 图片 ‘&’在 Excel 公式里用于拼接字符串、数值或单元格。在本例的拼接过程中,应用的是单引号。如果在某些编程语言中须要拼接出双引号的成果,能够用上面的公式: =B1&","&""""&A2&"""" SQL 间断解决多张数据表有些数据库因为应用了分表技术,同一类数据按既定规定保留在了某一张数据表中,如果偶然须要按条件解决一个数据,就必须遍历所有的表。 比方,当初有device_list_0到device_list_9 都用于存储设备相干信息,如果长期要删除device_no为78262170fa33 的记录,当时不晓得这条记录具体在哪张表,一个简略的办法就是间接每张表都删除一次。此时,能够借助 Excel 批量结构 SQL 语句。 关上Excel,在A1单元格写入公式: = "'device_list_"&ROW()-1&"'" 在B1单元格写入公式: ="delete from "&A1&" where 'device_no' = '78262170fa33';"这样,第一条语句就实现了。 选中A1:B1,往下复制公式到 A10:B10,就失去了全副所需的 SQL 语句! 利用这样的拼接思路,能够不便的实现各种程序语言外面的“反复代码”,大家能够依据理论状况灵活处理。 解决重复记录在开发和运维过程中,不可避免的要面对反复数据,尽管始作俑者不是本人,但须要加班解决的多半是本人。 ...

January 19, 2022 · 1 min · jiezi

关于excel:excel学习第2讲-单元格格式设置

第2讲 单元格格局设置应用单元格设置工具丑化表格1.设置单元格格局的对话框 选中一个单元格,工作栏小箭头;选中单元格-右键-设置单元格格局;选中一个区域-右键-设置单元格格局。A字体色彩。单元格背景填充色。表格边框线:边框-所有框线。合并多行单元格:合并且居中-逾越合并(选中区域按行合并)。2.对齐选项卡,设置文字对齐形式。3.设置边框线 选中区域-设置单元格格局-边框-斜线(内容:一个单元格内输出一行后分行-按alt+回车-靠左对齐-上一行加空格到左边)(插入-形态)格局刷:选中有格局的表-点击格局刷-再选中无格局的表;选中有格局的表格,双击格局刷,可任意改其余单元格,按esc退出。单元格数字格局1.数字格局 选中单元格-右键-设置单元格格局-数字选项卡-数值-小数位数、千分位分隔符。(单元格格局设置不会扭转值的大小,看编辑栏)货币VS会计专用日期:微软采纳1900计年形式(复制粘贴日期,变为数值,更改单元格格局)自定义(;;;暗藏),yyyy/mm/dd(日期设置),dd-mmm(英文月份简写)-yyyy,aaa(一到日),aaaa(星期一到日)。excel中数字分为:一种有大小多少的含意可加总,另一种没有这种含意可相连。excel中数值15位精确度。身份证号:选中一列-设置单元格格局-文本格式(文本数字左上角带绿箭头)文本不能通过间接设置单元格格局间接转换。一组数字相加为零,则可能为本文,选中后左上角点!号,转换为数字。一列数字不知是否有文本,全副乘以1,excel强制转换文本为数值。 应用分列工具txt文档数据复制到excel,间接粘贴,选中A列,数据选项卡-分列-分隔符号。用分列把文本格式的日期改为数值型。(文本格式与惯例格局用分列转换)

January 14, 2022 · 1 min · jiezi

关于excel:excel学习

第一讲 意识excelexcel软件简介公式必须以等号结尾,否则不会进行运算。要大范畴手工输出很多公式时省略等号,文件-选项-高级-Lotus(之前的数据处理软件)兼容性设置-转换Lotus123公式。(平时不倡议如此)excel能做什么数据存储、数据处理(函数利用)、数据分析、数据出现。excel界面介绍(课后本人看)excel中一些重要概念几种罕用文件类型a.XLS(2003版前)/XLSX (2007、2010版)工作簿文件b.XLW 工作区文件 (2013可能已勾销保留工作区的性能) 整个关上的是excel的主程序,两头区域是工作簿,用小的放大、放大及敞开键管制。须要切换两张表时: 视图-新建窗口-(若为两个窗口)全副重排-垂直并排-可同时看到两个表的内容(互为镜像,修 改时同时变动,便于比拟)。 重排后,再视图-保留工作区(当初表格的布局款式)(为XLW格式文件)。 工作区不保留数据,相当于只是个快捷方式(超链接),保留了表格的布局。对于工作簿、工作表、单元格的操作a.新建工作表:插入工作表按钮,在工作表标签上右键删除此工作表、重命名;重要工作表的标记-工作表标签色彩(改回无色彩);插入多张表,按shift连选(点第一个、最初一个)多张工作表,再插入工作表。b.横行竖列,定位单元格。 第四行前加一行,选中第四行,右键插入。删除整行。抉择多行-插入,会插入多个空行。替换两列秩序。选中单元格-把鼠标放在单元格边框线上-鼠标变为十字方向-能够把单元格拉走;选中一列,把鼠标放在选中的一列的边框线,鼠标变为方向箭头,按住shift拖拽(否替换)。调整行高列宽,双击会主动调整为可包容内容的长度;选中多列调整列宽,可把多列同时调整为同一宽度。如何达到一个表格的最初一行,选中一个有数据的单元格,鼠标挪动到单元格边线,下边线双击达到表格最初,上边线双击达到表格最上,左、右等等。(间断的数据区域)小工具解冻窗格(便于查看表头) 视图-解冻窗格-解冻首(勾销)解冻前几行:选中A4单元格-解冻窗格-解冻拆分窗格,则前三行被解冻。(解冻以后单元格单方)解冻A列:选中B4单元格-解冻拆分窗格,则前三行和A列都解冻。(解冻以后点选单元格的上方和左侧)填充柄(拖拽) 选中单元格,鼠标放于右下角,下拉。Ctrl键+:,会输出明天的日期。(下拉主动填充)下拉有两种:按序列和按复制,按ctrl建再下拉能够扭转下拉的品种。点右键下拉,抉择以何种形式填充。(例:以工作日填充)自定义拖拽程序:文件-选项-高级-创立用于排序和填充序列的列表-编辑自定义列表-新序列-输出序列-增加-确定。第二行选到第900行:名称框显示单元格名字,在名称框写A900,回车会到该格;名称框中输2:900,回车选中整个区域。批量填充:选中多行,输出值,ctrl+回车。

January 10, 2022 · 1 min · jiezi

关于excel:如何快速解除Excel表格工作表保护

1. 解除Excel表格工作表爱护的办法如下文档介绍了Excel表格解除工作表爱护的办法,根本的套路就是把excel表格改名一个压缩包文件,接着从压缩包文件中取出对应的sheet页面的配置xml文件,而后把该xml文件中的sheetProtection节点删除掉。最初把文件放入压缩包,并复原为原excel后缀。从新关上excel表格,该sheet页面的表格爱护已被解除。https://www.jianshu.com/p/b01...https://www.cnblogs.com/shadr... 2. 应用python疾速解除工作表爱护如果sheet页面比拟多,一一去批改比拟麻烦,所以这里提供一个应用python脚本疾速批改的计划: import osimport reimport xml.dom.minidomdef delete_protection_node(xml_file): doc = xml.dom.minidom.parse(xml_file) root = doc.documentElement for parent in root.childNodes: if(parent.tagName == 'sheetProtection'): root.removeChild(parent) with open(xml_file, 'w', encoding='UTF-8') as f: doc.writexml(f)walk_names = os.walk(r'xl\worksheets')for (directory, sub_directorys, file_names) in walk_names: for name in file_names: m = re.match(r'(.+\.)xml$', name, re.I) if m: delete_protection_node(os.path.join(directory, name))

December 14, 2021 · 1 min · jiezi

关于excel:用分列解决拆分excel中一列的数据场景

昨天遇到一个场景,从数据库中导出了一列汇合数据,在excel中一看,是拼接到一起的,如下图,我过后想的就是拆分这个单元格,把excel的数据进行拆分,当然绕了一大圈还是解决不了问题: 最初发现,此场景的解决形式是分列: 拆分excel中一列的数据,其实是分列,最初就能够把本人的须要数据离开:

December 14, 2021 · 1 min · jiezi

关于excel:Excel-2019如何利用条件格式限制输入数据

在对Excel进行数据输出时,为了确保单元格数据输出正确,能够应用数据有效性来限度输出数据的范畴。其实也能够用条件格局来达到该目标。例如为超过肯定数值的单元格主动加上色彩,比方一个单元格的数值下限设置为100,如果输出101,这个单元格就变成红色。 应用条件格局限度输出数据的具体操作步骤如下。 STEP01:抉择B2:G14单元格区域,切换至“开始”选项卡,在“款式”组中单击“条件格局”下三角按钮,在开展的下拉列表中抉择“突出显示单元格规定”选项,而后在开展的级联列表中抉择“大于”选项,如图5-60所示。 图5-60 抉择条件格局 STEP02:在关上的“大于”对话框中设置大于数值为“100”,设置显示为“绿填充色深绿色文本”,最初单击“确定”按钮返回工作表,如图5-61所示。 图5-61 设置数值条件 STEP03:如果在选定区域内输出了下限大于100的数值,则单元格就会被绿填充色深绿色文本填充,如图5-62所示。 图5-62 条件格局设置成果

November 24, 2021 · 1 min · jiezi

关于excel:如何通过-Excel-import-的方式导入测试数据到-SAP-Commerce-Cloud-服务器

登录 SAP Commerce Cloud Administration Cockpit,从下拉菜单里抉择 Product Cockpit: 点击这个箭头,关上 product 视图: 点击这个 excel import 按钮: 抉择好 excel 和 media.zip 之后,点击 import: 点击这个按钮查看 import 进度: 进到 Backoffice 页面,依据 excel 里的 product id 查看一个 product,确保导入胜利: 更多Jerry的原创文章,尽在:"汪子熙":

November 7, 2021 · 1 min · jiezi

关于excel:Excel海量数据导入mongodb

我的需要导入Excel的数据,供零碎内查问(将近30w行)这个Excel是一个全量的数据,不是增量,零碎外保护,有变动了,定期导入更新Excel导入尝试一般的poi导入excel的形式,数据量太大,很容易OOM WorkbookFactory.create(file.getInputStream());我的excel不过30M左右,程序占了3g内存,竟然还会OOM 参考这个问题:https://stackoverflow.com/que... 应用这个库,反对用流的形式读取excel:https://github.com/monitorjbl... 依赖援用仓库后,呈现了Method Not Found的异样,可能是依赖抵触了,我被动排除了一下 <dependency> <groupId>com.monitorjbl</groupId> <artifactId>xlsx-streamer</artifactId> <version>2.1.0</version> <exclusions> <exclusion> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.1.2</version> </dependency>应用xlsx-streamer读取excel:try ( InputStream is = file.getInputStream(); Workbook wb = StreamingReader.builder() // number of rows to keep in memory (defaults to 10) .rowCacheSize(100) // buffer size to use when reading InputStream to file (defaults to 1024) .bufferSize(4096) // InputStream or File for XLSX file (required) .open(is); ) { ……}导入mongodb数据量比拟大,如果组装java对象,必定节约性能,我抉择间接用 org.bson.Document组装数据。 ...

September 8, 2021 · 2 min · jiezi

关于excel:导出zip

管制层@PostMapping("/questionListExport")@ApiOperation(httpMethod = "POST",value = "",notes = "列表导")public WGJsonResult questionListExport(@RequestBody BackQuestionExport param, HttpServletResponse response) throws Exception { return backQuestionService.questionListExport(param,response);}服务层@Overridepublic WGJsonResult questionListExport(BackQuestionExport param, HttpServletResponse response) throws IOException { PageHelper.startPage(param.getPageNo(),param.getPageSize()); List<BackQuestionExport> eports = backQuestionMapper.questionListExport(param); Map<String,List<BackQuestionExport>> dataMap = eports.stream().collect(Collectors.groupingBy(p->p.getInvitName()+"_"+p.getInvitId(), Collectors.toList())); exportExcel(response, dataMap); //导出之后记录日志 ask_exp_imp_record addLog(eports,1); return success("下载胜利");}private void exportExcel(HttpServletResponse response, Map<String, List<BackQuestionExport>> map) throws IOException { SimpleDateFormat sdf4 = new SimpleDateFormat("yyyy_MM_dd_hh_mm_ss"); String nowDate = sdf4.format(new Date()); String fileName = nowDate + ".zip"; // 获取我的项目根门路 String rootPath =System.getProperty("user.dir")+"_"+nowDate;// System.out.println("-----------"+System.getProperty("user.dir")); File f = new File(rootPath); if (!f.exists()) { f.mkdirs(); } String tempPath = ""; response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(rootPath + File.separator + fileName)); try { for (Map.Entry<String, List<BackQuestionExport>> entry : map.entrySet()) { String k = entry.getKey(); List<BackQuestionExport> value = entry.getValue(); tempPath = rootPath + File.separator + k + ".xlsx"; EasyExcel.write(tempPath, BackQuestionExport.class).sheet("问答数据").doWrite(value); //创立输出流读取文件 BufferedInputStream bis = new BufferedInputStream(new FileInputStream(tempPath)); //将文件写入zip内,行将文件进行打包 zipOutputStream.putNextEntry(new ZipEntry(nowDate+File.separator+k + ".xlsx")); //写入文件的办法,同上 int size = 0; byte[] buffer = new byte[1024]; //设置读取数据缓存大小 while ((size = bis.read(buffer)) > 0) { zipOutputStream.write(buffer, 0, size); } bis.close(); } //敞开数据流,留神敞开的程序 zipOutputStream.close(); FileInputStream fis = new FileInputStream(rootPath + File.separator + fileName); BufferedInputStream buff = new BufferedInputStream(fis); byte[] b = new byte[1024];// 相当于咱们的缓存 int k = 0;// 该值用于计算以后理论下载了多少字节 OutputStream out = response.getOutputStream();// 从response对象中失去输入流,筹备下载 // 开始循环下载 while ((k = buff.read(b)) > 0) { out.write(b, 0, k); } out.close(); buff.close(); } catch (Exception e) { System.out.println(e.fillInStackTrace()); } finally { if (!f.exists()) return; if (f.isFile()) { f.delete(); return; } File[] files = f.listFiles(); for (int i = 0; i < files.length; i++) { files[i].delete(); } f.delete(); }}sql<select id="questionListExport" resultMap="UserBackQuestionExpMap"> SELECT * FROM ( SELECT ic.question_id, ic.id, ic.invit_id, ic.invit_name, DATE_FORMAT( ic.insert_time, '%Y-%m-%d %H:%i:%S' ) insert_time, ic.is_export, aq.question, aq.label_value, aq.lable_name, aq.`describe`, REPLACE ( uc.file_path, ',', ',\\n' ) file_path, IF(ak.answer IS NOT NULL,1,0) answerFlag FROM invit_contact ic LEFT JOIN ask_question aq ON ic.question_id = aq.id LEFT JOIN ( SELECT table_id, GROUP_CONCAT( file_path ) file_path FROM upload_change WHERE table_name = 'ask_question' GROUP BY table_id ) uc ON uc.table_id = ic.question_id LEFT JOIN (SELECT question_id, GROUP_CONCAT( ak.result SEPARATOR ',' )as answer FROM ask_question aq LEFT JOIN ask_answer ak ON aq.id = ak.question_id GROUP BY ak.question_id ) ak ON ic.question_id = ak.question_id WHERE aq.is_del = 0 )f <include refid="SearchSql"/> ORDER BY insert_time DESC</select>

August 16, 2021 · 2 min · jiezi

关于excel:导入文件

实体@ColumnWidth(20)@HeadRowHeight(15) // 题目高度@ContentRowHeight(15) // 文本行高度public class BackQuestionImport extends BaseRowModel {@ExcelProperty( ")@ApiModelProperty(value="id")private int id;@ExcelProperty( "问题id")@ApiModelProperty(value="问题id")private int questionId;@ExcelProperty( "专家id")private int invitId;@ExcelProperty( "专家名字")private String invitName;@ExcelProperty( "发问日期")private String insertTime;@ExcelProperty( "问题题目")private String question;@ExcelProperty( "标签id")private String labelValue;@ExcelProperty( "标签名称")private String lableName;@ExcelProperty( "问题形容")private String describe;@ExcelProperty( "图片")private String filePath;@ExcelIgnore@ApiModelProperty(value="是否导出")private Integer exportFlag;@ExcelProperty( "专家答复")@ApiModelProperty(value="专家答复")private String answer;管制层@PostMapping("/questionListImport")@ApiOperation(httpMethod = "POST",value = "",notes = "")public WGJsonResult questionListImport(@RequestParam("file") MultipartFile multipartFile) throws IOException { return backQuestionService.questionListImport(multipartFile);}服务层@Overridepublic WGJsonResult questionListImport(MultipartFile multipartFile) throws IOException { Sheet sheet = new Sheet(1, 1, BackQuestionImport.class); List<Object> readList = EasyExcelFactory.read(multipartFile.getInputStream(), sheet); // 存 BackQuestionExport 实体的 汇合 List<BackQuestionExport> list = new ArrayList<BackQuestionExport>(); for (Object obj : readList) { BackQuestionExport backQuestionExport = new BackQuestionExport(); BeanUtils.copyProperties(obj,backQuestionExport); list.add(backQuestionExport); } //插入ask_answer backQuestionMapper.addQuestionAnswerData(list); //记录日志 ask_exp_imp_record addLog(list,2); return success("导入胜利");}sql语句 INSERT INTO ask_answer ( id, result, label_value, lable_name, user_id, user_name, question_id ) VALUES <foreach collection ="list" item="item" index= "index" separator =","> ( #{item.id}, #{item.answer}, #{item.labelValue}, #{item.lableName}, #{item.invitId}, #{item.invitName}, #{item.questionId} ) </foreach > ON DUPLICATE KEY UPDATE id = VALUES(id), result = VALUES(result), label_value = VALUES(label_value), lable_name = VALUES(lable_name), user_id = VALUES(user_id), user_name = VALUES(user_name), question_id = VALUES(question_id) 记录日志 ask_exp_imp_recordpublic void addLog(List<BackQuestionExport> list,Integer type){ //获取各个数据的汇合 List<String> questions = list.stream().map(BackQuestionExport::getQuestion).distinct().collect(Collectors.toList());//先获取问题汇合 List<Integer> questionIds = list.stream().map(BackQuestionExport::getQuestionId).distinct().collect(Collectors.toList()); List<Integer> invitIds = list.stream().map(BackQuestionExport::getInvitId).distinct().collect(Collectors.toList()); List<String> invitNames = list.stream().map(BackQuestionExport::getInvitName).distinct().collect(Collectors.toList()); List<String> answers = list.stream().map(BackQuestionExport::getAnswer).distinct().collect(Collectors.toList()); List<Integer> ids = list.stream().map(BackQuestionExport::getId).distinct().collect(Collectors.toList()); //保留记录 BackQuestionLog backQuestionLog = new BackQuestionLog(); backQuestionLog.setQuestionIds(questionIds.stream().map(String::valueOf).collect(Collectors.joining(",")).trim()); backQuestionLog.setQuestions(questions.stream().map(String::valueOf).collect(Collectors.joining(",")).trim()); backQuestionLog.setQuestionNum(questionIds.size()); backQuestionLog.setAnswerManIds(invitIds.stream().map(String::valueOf).collect(Collectors.joining(",")).trim()); backQuestionLog.setAnswerManNames(StringUtils.join(invitNames, ",").trim()); backQuestionLog.setAnswerIds(ids.stream().map(String::valueOf).collect(Collectors.joining(",")).trim()); backQuestionLog.setAnswers(answers.stream().map(String::valueOf).collect(Collectors.joining(",")).trim()); backQuestionLog.setAnswerNum(answers.size()); backQuestionLog.setType(type); backQuestionLog.setStatus(0); //插入日志表 ask_exp_imp_record backQuestionMapper.addQuestionAnswerLog(backQuestionLog);}

August 16, 2021 · 2 min · jiezi

关于excel:导入EXCEL可读取json

此处为须要插件 xlsx此处为vue父组件引入办法 // import excel from "./components/upload-excel.vue"; // <excel v-on:getResult="updateExcel"></excel>此处为编辑好的vue组件 <template> <div> <span> <input class="input-file" hidden="hidden" type="file" @change="exportData" accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel" /> <a-button class="m-x-10" type="primary" @click="btnClick"> 导入 </a-button> </span> </div></template><script> //图标组件要独自引入 import { defineComponent, reactive, onMounted, toRefs, computed } from "vue"; // import { UpOutlined, DownOutlined } from '@ant-design/icons-vue'; // import { message } from 'ant-design-vue'; // import { useStore } from 'vuex'; // import { useApi } from '@/common/utils/api'; export default defineComponent({ components: {}, setup(props, context) { const data = reactive({}); const methods = { btnClick() { document.querySelector(".input-file").click(); // }, exportData(event) { if (!event.currentTarget.files.length) { return; } // 拿取文件对象 const f = event.currentTarget.files[0]; // 用FileReader来读取 const reader = new FileReader(); // 重写FileReader上的readAsBinaryString办法 FileReader.prototype.readAsBinaryString = function (f) { let binary = ""; let wb; // 读取实现的数据 let outdata; // 你须要的数据 const reader = new FileReader(); reader.onload = function (e) { // 读取成Uint8Array,再转换为Unicode编码(Unicode占两个字节) const bytes = new Uint8Array(reader.result); const length = bytes.byteLength; for (let i = 0; i < length; i++) { binary += String.fromCharCode(bytes[i]); } // 接下来就是xlsx了,具体可看api //上行必须加上,否者报错 // eslint-disable-next-line @typescript-eslint/no-var-requires const XLSX = require("xlsx"); wb = XLSX.read(binary, { type: "binary", }); outdata = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]); // 自定义办法向父组件传递数据 // console.log("outdata = " + JSON.stringify(outdata)); // console.log(outdata); context.emit("getResult", outdata); }; reader.readAsArrayBuffer(f); }; reader.readAsBinaryString(f); }, }; return { ...toRefs(data), ...methods, }; }, });</script>

June 29, 2021 · 1 min · jiezi

关于excel:前端可视化展示Excel

Excel可视化后端返回Excel流前端进行展现前言需要:有的时候咱们须要接管到后端返回的Excel流,前端进行可视化展现时,这个时候依照如下步骤即可 提前阐明:前端展现的Excle款式与格局齐全由后端管制,比方合并单元格、款式管制.. 前端Demo:例子 (有现成写好的接口) 装置依赖库装置依赖库(二选一即可) npm install xlsx xlsx-style less less-loader@5.0.0yarn add xlsx xlsx-style less less-loader@5.0.0拷贝文件夹 src/components/x-spreadsheetsrc/util/xlsx-exchange戳我下载引入依赖:在你想申请展现的.vue文件中import axios from 'axios'import Spreadsheet from '@/components/x-spreadsheet';import XStyle from 'xlsx-style';import Exchange from '@/util/xlsx-exchange';启动我的项目:批改报错 cpexcel.js (ctrl+p间接搜寻文件即可)(删除)-- var cpt = require('./cpt' + 'able');(增加)++ var cpt = cptable;展现定义template<div class="content"> <div id="xss-demo" /></div>定义datadata() { return { sheet: null, flobFileSize: 0, }},初始化xsheetasync mounted() { this.instantiateSheet();},xsheet配置method: { // 设置xsheet 数据 setXsheetData(out) { this.sheet.loadData(out); if (out.length) { let colLen = Object.keys(out[0].rows[0].cells).length || 10; // let colLen = this.getTableColLen(out) || 10; let rowLen = Object.keys(out[0].rows).length || 10; this.sheet.sheet.data.rows.len = rowLen; this.sheet.sheet.data.cols.len = colLen; this.sheet.reRender(); } }, // 实例化 xsheet instantiateSheet() { let queryListHeight = 0; if (this.$refs.queryList) queryListHeight = this.$refs.queryList.$el.offsetHeight || 0; this.sheet = new Spreadsheet(document.getElementById("xss-demo"), { mode: "read", // edit | read showToolbar: false, showGrid: false, showContextmenu: false, view: { height: () => document.documentElement.clientHeight - 180 - queryListHeight, width: () => document.documentElement.clientWidth - 300, }, row: { height: 25, len: 100, }, col: { len: 16, width: 100, indexWidth: 60, minWidth: 60, }, }); },}发送申请axios({ url: 'http://39.102.36.212:3006/excelExport', method: 'post', responseType: 'blob'}).then((res) => { const self = this const result = res.data this.flobFileSize = result.size || 0; if (result instanceof Blob) { var reader = new FileReader(); reader.onload = function (e) { let data = e.target.result; console.log(data) if (data) { let workbook = XStyle.read(data, { type: "binary", cellStyles: true }); let out = Exchange.stox(workbook); self.setXsheetData(out) } else { self.setXsheetData([]) } }; reader.readAsBinaryString(result); } else { self.setXsheetData([]) }})展示成果 ...

May 30, 2021 · 2 min · jiezi

关于excel:Excel-解决csv丢失前面的0

背景:Excel中文本格式存储的后面带0的数字,但在存成CSV时,前0是没有失落的(能够提前用Notepad++关上看一下) 步骤:1.新建一个空白excel并关上,2.数据->自文本-> 抉择方才另存为的那个csv(看起来不显示前0的)-> 导入->下一步->下一步->列数据格式抉择文本->实现-确定。 ->> 列数据格式抉择文本,并抉择对应要改为Test的列。 参考资料: Csv 失落后面的零

May 11, 2021 · 1 min · jiezi

关于excel:excel-按照模板导出-springboot实战电商项目mall4j

在统计数据的时候,咱们须要导出一些特定格局的excel。咱们能够应用poi写代码来解决格局,这样会导致写很多的代码来搞定,如果将某两个特定的表格数据的地位或者色彩标记做小小的改变,咱们只有调整一下代码能力搞定。那有没有一种简略的办法导出特定排列的excel呢?答案当然是有的,这里举荐easypoi来解决这个问题。如有更好解决方案欢送留言探讨哦。 springboot实战电商我的项目mall4j (https://gitee.com/gz-yami/mall4j) java开源商城零碎 1.easypoi简介easypoi性能如同名字easy,主打的性能就是容易,让一个没见接触过poi的人员就能够不便的写出Excel导出,Excel模板导出,Excel导入,Word模板导出,通过简略的注解和模板语言(相熟的表达式语法),实现以前简单的写法。easypoi官网文档 2.为什么选用easypoi次要看重easypoi的两个性能,Excel模板导出,html预览。Excel模板导出,是为了少写一下反复大量的代码,导出一些简单排列的表格。html预览,有时候咱们想先看一些导出成果,不想导出,就须要这个html预览的性能。当然easypoi还有一些其余的性能,请到esaypoi的官网文档去查看吧。 3.引入依赖咱们这里引入是spring boot 的依赖,其余的能够到官网查看,参照引入。 <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-spring-boot-starter</artifactId> <version>4.0.0</version></dependency>4.Excel模板导出先定义一个excel的模板,如图所示:而后定义好相干变量,如图所示 5.代码局部 @RequestMapping("test") public void getExcelInfo(ModelMap modelMap, HttpServletRequest request, HttpServletResponse response) throws IOException { // 模板在我的项目中的门路 TemplateExportParams params = new TemplateExportParams( "doc/testExcelTemplate.xlsx"); Map<String, Object> map = new HashMap<String, Object>(16); map.put("code", "A20210101"); map.put("applyTime", "2021-01-01"); map.put("total", 40000); map.put("company", "执笔潜行科技有限公司"); map.put("remark", "测试导出"); map.put("year", "2021"); map.put("month", "04"); map.put("day", "25"); map.put("name", "JueYue"); map.put("phone", "1879740****"); List<Map<String, String>> listMap = new ArrayList<>(); for (int i = 0; i < 4; i++) { Map<String, String> lm = new HashMap<String, String>(16); lm.put("amountType", i + "测试"); lm.put("code", "A001"); lm.put("subjectName", "设计"); lm.put("projectName", "EasyPoi " + i + "期"); lm.put("fullName", "Ces 我的项目"); lm.put("bankCard", "6216610200016587010"); lm.put("bankName", "中国银行"); lm.put("applyAmount", i * 10000 +""); lm.put("approvedAmount", i * 10000 +""); listMap.add(lm); } map.put("list", listMap); modelMap.put(TemplateExcelConstants.FILE_NAME, "专项收入用款申请书_map.xls"); modelMap.put(TemplateExcelConstants.PARAMS, params); modelMap.put(TemplateExcelConstants.MAP_DATA, map); PoiBaseView.render(modelMap, request, response, TemplateExcelConstants.EASYPOI_TEMPLATE_EXCEL_VIEW); }输出门路拜访下载测试,后果如图: ...

April 29, 2021 · 1 min · jiezi

关于excel:SkillVBA零基础入门及实例批量将链接转成图片

简介VBA(Visual Basic for Applications)是附丽在应用程序(例如Excel)中的VB语言。只有你装置了Office Excel就主动默认装置了VBA,同样Word和PowerPoint也能调用VBA对软件进行二次开发而让一些特地简单的操作“脚本化”。 如何关上VBA1. 关上”开发工具“性能(首次应用VBA)如果你是第一次应用VBA,须要关上“开发工具”性能。 Window:文件——选项——自定义功能区——勾选开发工具 Mac:Excel——偏好设置——视图 2. 关上VBA的三种形式2.1 开发工具——VisualBasic 2.2 ALT+F11快捷键2.3 右键sheet页查看代码 3. VBA界面 一个简略的VBA程序大部分程序入门都会写一个代码输入“Hello World”,咱们写第一个程序在选定的单元格输入本人的昵称。 Sub 插入文字() 'sub定义一个过程 Selection.Value = "TOMOCAT" '代码块End Sub '完结一个过程1. 新建模块模块不便咱们导出代码用于其余的Excel,所以养成良好的编程习惯插入模块。 2. 在指定区域写代码 3.执行代码上面三种办法实现的性能雷同,毋庸太纠结,抉择最不便的即可。 F5执行运行选项卡 运行按钮 一点小倡议——应用“立刻窗口”如果你用过Rstudio写R代码或者Spyder写Python代码的话,“立刻窗口”相似于控制台,能提醒代码编译谬误和进行实时计算。 1. 关上“立刻窗口视图——立刻窗口 2. 在立刻窗口输出代码间接作用于excel选中一个单元格,而后在立刻窗口输出代码(不用定义Sub过程),敲击回车键执行: 能够看到执行后被选中的单元格呈现了你的昵称,到此为止你曾经实现了第一个VBA程序。 实例:将URL转化成图片1. 背景形容当初excel中有多个图片链接,咱们心愿将这些链接都转成图片。 2. 办法一:同时保留链接和图片开发工具——Visual Basic(或者ALT+F11快捷键)进入VB界面,而后双击sheet1按钮关上VB编程窗口: 输出如下代码并保留: Sub loadimage()Dim HLK As Hyperlink, Rng As RangeFor Each HLK In ActiveSheet.Hyperlinks '循环流动工作表中的各个超链接 If HLK.Address Like "*.jpg" Or HLK.Address Like "*.gif" Or HLK.Address Like "*.png" Then '如果链接的地位是jpg或gif图片(此处仅针对此两种图片类型,更多类型能够通过建设数组或字典或正则来判断) Set Rng = HLK.Parent.Offset(, 1) '设定插入指标图片的地位 With ActiveSheet.Pictures.Insert(HLK.Address) '插入链接地址中的图片 If .Height / .Width > Rng.Height / Rng.Width Then '判断图片纵横比与单元格纵横比的比值以确定针对单元格缩放的比例 .Top = Rng.Top .Left = Rng.Left + (Rng.Width - .Width * Rng.Height / .Height) / 2 .Width = .Width * Rng.Height / .Height .Height = Rng.Height Else .Left = Rng.Left .Top = Rng.Top + (Rng.Height - .Height * Rng.Width / .Width) / 2 .Height = .Height * Rng.Width / .Width .Width = Rng.Width End If End With End IfNextEnd Sub开发工具-宏-执行: ...

April 10, 2021 · 2 min · jiezi

关于excel:10w-行级别数据的-Excel-导入优化记录

需要阐明 我的项目中有一个 Excel 导入的需要:缴费记录导入 由施行 / 用户 将别的零碎的数据填入咱们零碎中的 Excel 模板,利用将文件内容读取、校对、转换之后产生欠费数据、票据、票据详情并存储到数据库中。 在我接手之前可能因为之前导入的数据量并不多没有对效率有过高的谋求。然而到了 4.0 版本,我预估导入时Excel 行数会是 10w+ 级别,而往数据库插入的数据量是大于 3n 的,也就是说 10w 行的 Excel,则至多向数据库插入 30w 行数据。因而优化原来的导入代码是势在必行的。我逐渐剖析和优化了导入的代码,使之在百秒内实现(最终性能瓶颈在数据库的处理速度上,测试服务器 4g 内存不仅放了数据库,还放了很多微服务利用。解决能力不太行)。具体的过程如下,每一步都有列出影响性能的问题和解决的方法。 导入 Excel 的需要在零碎中还是很常见的,我的优化方法可能不是最优的,欢送读者在评论区留言交换提供更优的思路 一些细节 数据导入:导入应用的模板由零碎提供,格局是 xlsx (反对 65535+行数据) ,用户依照表头在对应列写入相应的数据数据校验:数据校验有两种: 字段长度、字段正则表达式校验等,内存内校验不存在内部数据交互。对性能影响较小数据重复性校验,如票据号是否和零碎已存在的票据号反复(须要查询数据库,非常影响性能)数据插入:测试环境数据库应用 MySQL 5.7,未分库分表,连接池应用 Druid迭代记录 第一版:POI + 逐行查问校对 + 逐行插入 这个版本是最古老的版本,采纳原生 POI,手动将 Excel 中的行映射成 ArrayList 对象,而后存储到 List ,代码执行的步骤如下: 1.手动读取 Excel 成 List 2.循环遍历,在循环中进行以下步骤 测验字段长度一些查询数据库的校验,比方校验以后行欠费对应的屋宇是否在零碎中存在,须要查问屋宇表写入以后行数据返回执行后果,如果出错 / 校验不合格。则返回提示信息并回滚数据3.不言而喻的,这样实现肯定是赶工赶出来的,后续可能用的少也没有察觉到性能问题,然而它最多实用于个位数/十位数级别的数据。存在以下显著的问题: 查询数据库的校验对每一行数据都要查问一次数据库,利用拜访数据库来回的网络IO次数被放大了 n 倍,工夫也就放大了 n 倍写入数据也是逐行写入的,问题和下面的一样数据读取应用原生 POI,代码非常冗余,可维护性差。第二版:EasyPOI + 缓存数据库查问操作 + 批量插入 ...

March 29, 2021 · 3 min · jiezi

关于excel:只会用Excel做数据试试这个Excel插件用过的人都真香

BI商业智能,这个词想必大家都听过了。益处就用不我一一提了:简略易用,不必写代码;疾速取数,4秒导入亿行数据;数据可视化,活泼形象……然而很多共事对BI又爱又恨,恨的是这个工具尽管“好用”,然而我最习惯的还是Excel,新工具还要重新学习,太麻烦了! 不可否认的是,Excel给大家的职业生涯开了个好头,对刚入行的小白来说,熟练掌握Excel剖析和报表制作技巧还能理解一些数据挖掘常识,很快就能在同批老手数据分析师中怀才不遇。 然而Excel一旦遇到简单的大数据量数据集就卡得要死,效率很低。再加上数据无奈实时更新,须要消耗很多反复人力在更换数据源上,并且可视化成果也无限。 起初因为太多员工都在吐槽Excel的这个问题,主管也开始器重起来。他“埋伏”各个顶尖数据分析师的聊天群里,发现了其余公司解决Excel导数难的方法。他们下载了一款插件,据说插件十分小,只有3.4M,然而用了它,上亿的数据放到Excel里也不会卡顿。 另外,还不须要下载其余的破解安装包,下载好一键装置! Excel插件 据说还有其余的长处 1、功能强大且全面,反对微软Office和WPS Office Excel剖析插件内置了大量实用功能,平时须要3/4/5/6个步骤,甚至要记住多个公式的操作。当初都变成了傻瓜式的一键操作,效率晋升 100 倍!同时还兼容微软Office和WPS Office! 2、反对超大数据量解决,秒级速度响应亿级数据 反对Excel直连数据库,在Excel里间接拖拽字段就能够刷新数据。上亿行的数据也能够10秒内导入! 3、收费,易上手! 收费,收费,收费!重要的事件说三遍!这么酷炫的性能插件,竟然还是收费的,几乎不要太良心。 能遇见这样优良又收费的BI工具着实让我领会到了国产真香,再想到之前华为被美国“封杀”的事,也让大部分的企业意识到国产工具的不可替代性。

March 18, 2021 · 1 min · jiezi

关于excel:想解决一线业务用户的问题这款好用的excel插件必不可少

随着科技的倒退,人们对数据分析的要求越来越多, Excel也存在一些问题,长期困扰一线业务用户:首先是性能问题。对于大数据量,Excel解决起来很慢。数据获取的过程麻烦,特地是周期性的数据获取,每次都要找IT人员帮忙,再粘贴到excel中去。首先,文件满天飞,不好治理;其次,权限不好管制,没法做到只共享剖析后果,而不共享明细数据;最初,数据没法做到每个人的数据不同,依据用户权限动静更新数据。 因而许多公司开发了很多简略易用、高效的第三方插件,Smartbi的excel插件就是面向Excel用户的数据分析工具,Smartbi的excel插件又叫Smartbi电子表格。它联合了Excel的长处,解决了Excel的问题。 Smartbi电子表格是企业报表平台的解决方案专家,翻新的基于Excel实现报表设计,满足各种格局的行业监管报表、外部治理报表的需要。包含:清单报表、穿插报表、分组报表、多源分片报表、分块报表、表单报表、图形报表、回写报表、假如剖析报表、二次计算报表、套打报表、段落式报表、预警报表(Excel条件格局)、组合报表(智能评语)。 报表开发人员制作和应用电子表格的次要过程为: 首先先装置Smartbi Excel插件,按管理员调配的账号从Excel登录插件;而后在左侧设计动态表样,而后从右侧数据集面板拖拽字段到报表区域进行排版;接着调整字段的单元显示格局,如设置汇总求和、阈值告警等;最初将制作好的电子表格公布到报表服务器,能够在Excel或者前端浏览器预览导出打印报表。 Smartbi 电子表格的八大个性: Excel是用户最相熟的办公软件,有着最敌对的UI操作体验 反对Excel的单元格计算、行列锁定、数据有效性等各种罕用性能 反对Excel的条件格局(数据条、图标集、色阶)性能 反对Excel所有函数,例如财务函数、统计函数、逻辑函数、三角函数等 反对杜邦剖析、工夫序列预测等,并能够应用宏进行扩大 反对应用第三方Excel模板,如丑化巨匠,来对表格和图形进行丑化 报表制作充沛简化,间接将数据字段拖拽到Excel模板上,公布即可。 具备弱小的透视剖析性能,包含:工夫计算二次计算性能;累值和日均、增长值和增长率的工夫计算;度量区域字段聚合操作。 对于Excel插件的下载  主动装置      1)装置Microsoft .Net Framework 4.0 Full      2)获取装置介质          插件安装包不蕴含在规范的产品安装包中,若需对插件进行学习或应用,         请到官网进行 下载;      3)点击装置介质,弹出装置界面如图: 装置步骤 参考装置详情 启动Excel插件装置实现后,启动Excel,会呈现Smartbi面板。 点击"设置",填写拜访地址、您的账号、明码;并且抉择默认报表类型=Excel剖析。

March 16, 2021 · 1 min · jiezi

关于excel:SmartbiEXCEL憋出大招逆袭大数据的黑马出现了

EXCEL是一款功能强大的数据可视化和剖析工具,其直观的界面、杰出的计算性能受到了全世界所有用户的青眼。通过Excel,你能够利用模板轻松创立电子表格,能够应用公式去执行简单的数学运算,还能够应用图形、迷你图去展现你手中的数据。EXCEL的内存占用较低、体积玲珑,是一款性能十分弱小的办公软件,能够这么说,只有用windows操作系统的电脑,大部分的人都会装置这一款软件。微软官网已经统计过,每五个成年人中就有一个人会应用EXCEL,足以阐明EXCEL的影响力有多大了。 可是EXCEL并不是一个十分完满的办公软件,就好比是女神维纳斯的雕像一样,即便是身材比例十分柔美,然而因为没有手臂而造成了一个十分的缺点。EXCEL就是这样的一款不完满的办公软件,就解决拿大容量的数据来说吧,只有超过百万行数据量的报表,EXCEL便十分吃力,如果超过千万行数据量,EXCEL便无能为力,只能望洋兴叹了。做大数据通常须要借助其余工具去实现,如果不会写代码或者会操作工具的话,对于普通用户来说几乎是一个噩梦般的事件。 做大数据要解决的问题,次要以下三个,第一个是数据量的问题,EXCEL的性能只能解决小容量的数据,算是一款轻量级的数据工具,如果要解决宏大的数据量,还是要用到数据库去解决。第二个是自动化的问题,在当初这个时代,企业外部每天产生的数据量都是数以万计的,甚至更多,如果还用简略的复制粘贴基本应酬不了这么宏大的数据量,所以数据分析师都是利用代码去执行一些根本的操作。第三个要解决利用场景的问题,也就是如何挖掘出更有价值的信息,通过数据精准地领导业务部门去做晋升和改善。 1、 数据性能 数据性能始终是EXCEL用户的心病,咱们刚刚也说过了,只有数据量一大,EXCEL就没辙了,所以解决大数据肯定要用数据库软件。然而很多EXCEL的用户不懂得怎么应用数据库,更不晓得怎么用EXCEL去连贯数据库了。网上有很多EXCEL连贯数据库的教程,但我感觉太简单了,还不如去用一个插件,我集体用的是一个叫Smartbi智剖析的插件,只有 装置好了,在EXCEL里就会呈现一个新的工具栏,抉择数据导入就能够把EXCEL或者CSV文件导进去进行剖析了。 如果你有内部的数据库,也能够与Smartbi智剖析建设连贯,例如阿里云或者MYSQL等市场上支流的数据库,只须要通过简略的设置,便能够开始应用内部数据库里的数据去进行剖析了。 数据建设了连贯后,就能够在EXCEL去拉拽数据进行剖析了,从此你再也不须要关上宏大的数据源了,只有用EXCEL这个工具便能够做大数据的剖析了。 2、 数据自动化 做数据查问免不了的是要写查问语句,置信很多人看到以下这样的SQL查询语言都会头疼,毕竟要熟练掌握数据库是须要肯定的技术的。然而这里就不教大家去应用数据库查问数据了,上面介绍两个十分弱小的办法。 即席查问:即席查问和SQL语句其实是一个意思,其目标都是为了查问出精确的数据,然而即席查问比SQL语句好的是,就是即席查问不必写语句。例如我在Smartbi智剖析上操作即席查问,只有通过鼠标就能把须要的数据字段筛选进去,而后就能够独自作为一个数据集保留在文件夹里,不须要从新关上总的数据源了。对于每天须要一直去写SQL的同学来说,这个办法能够帮你省掉不少功夫。 透视剖析:透视剖析也是一个罕用的性能,在EXCEL上咱们常常会用到透视图去剖析数据,然而面对几千万行的大数据来说,就无能为力了。因而云端的透视剖析会是一个十分好的抉择,通过云端的服务器对大数据进行高效地解决,几秒钟之内便能够刷出你想要的数据。上面是我在Smartbi智剖析模仿的一个透视剖析,数据量有9800万行,然而我通过简略的拉拽操作就把数据刷进去了,能够说,透视剖析对于解决大数据是熟能生巧的。 3、 数据挖掘 EXCEL在数据摸索上的性能远不如业余的BI软件,尽管EXCEL本身提供了不少图形组件,但从效率上来说,EXCEL做数据可视化还是比拟耗时的,每个图形都要通过大量的调整,能力最终失去符合要求的图形。而BI软件就不一样了,具备了十分丰盛的图形组件,只有通过简略拉拽便能够把数据出现进去。上面是我利用Smartbi智剖析去做进去的一个仪表盘,从整体布局来说,整体十分协调,左右也很对称,色彩也十分合乎大家审美,最重要的是还能实现数据动静展现,鼠标点到哪,哪里就会呈现数据。仪表盘的外围价值在于数据摸索,通过图形化的形式的去找出业务上的问题,对于管理者来说,他人给你汇报多少货色都没用,只有看数据就好了,用数据谈话才是硬道理。 人工智能、大数据、云计算和物联网的将来倒退值得器重,均为前沿产业,如果想要走在他人的后面,那就不要老是用EXCEL去做复制粘贴的事件了,好好地去把握和纯熟应用一门大数据的解决办法吧,置信升职加薪是不可企及的事件。

March 15, 2021 · 1 min · jiezi

关于excel:SmartbiEXCEL终于活成了你想要的样子性能已提升10倍

Excel在解决大数据量时顾此失彼的体现,已经让很多用户抓狂,EXCEL性能弱曾经是一个不争的事实。家喻户晓,EXCEL的解决下限是100万行,如果超过了100万行,EXCEL便大刀阔斧了,即便数据量只有几万行,EXCEL也会变得十分卡,对于习惯应用EXCEL的用户来说,这无疑是一个十分头疼的事件。 最近从敌人口中晓得了一个十分厉害的办法,能够帮忙EXCEL解决性能弱的问题,那就是利用插件的模式去连贯数据库,先把文件导入到插件里的本地数据库,而后再回到EXCEL里与数据库进行相连,调用数据库的数据字段,便能够在EXCEL里实现解决大容量数据的性能。为了验证这个办法是否无效,我把这个插件装置在了EXCEL里,随后能够看到工具栏里呈现了一个新的界面。 接下来的几天里我对这个插件进行了简略试用,发现它很不简单,这个插件不仅能够和数据库相连,还能实现其余更加厉害的性能,上面我简略介绍一下这个厉害的EXCEL神器——Smartbi智剖析的excel插件。 1、数据库连贯 随着信息时代的愈发成熟,企业的数据量也在每天呈爆炸式的增长,性能孱弱的EXCEL曾经不能满足大部分企业的需要,因而数据库成了各大企业存储和加工数据的首选。微软也为EXCEL提供了连贯数据库的性能,然而连贯过程较为简单,须要输出的用户名、明码、ip地址都是明文,十分不平安。 这个时候就须要用上咱们的Smartbi智剖析的excel插件了,它在数据库的连贯上提供了十分便当的操作环境,反对本地数据库、关系数据库、多维数据库、NOSQL等市面上支流的数据库端口。连贯过程也非常简单,以MySQL数据库为例,在连贯窗口抉择数据库类型,并填写好连贯串、用户明码,而后点击测试连贯,测试胜利之后点击保留,便实现数据连贯的创立了。 只有连贯好了数据库,就能在EXCEL中通过拖拽的形式调用数据库中的字段,无需再关上宏大的数据源文件了,对于EXCEL用户来说几乎是一个天大的好消息。 2、ETL技术 个别状况下,从各个业务部门汇总过去的数据是非常扩散的,无奈满足数据分析的需要,还要通过进一步的加工解决,最终造成简洁、标准、清晰的样本数据。这个过程通常被称为ETL,也就是对数据进行抽取(Extract)、荡涤转换(Transform)、加载(Load)的过程。在EXCEL上,微软为用户提供了power query的组件,依赖于M语言,能够对数据源进行关联,转置、分拆、过滤等操作,然而power query受引擎性能的局限,且M语言书写不不便,不适宜解决企业级数据。 我更偏向于在业余的ETL工具里实现这个过程,目前在国内用的最多的ETL工具是kettle,然而这个工具的性能相对来说比拟弱,而且呈现的一些bug无奈解决。所以我采纳了Smartbi智剖析里的自助ETL技术去实现这个工作,它在ETL的解决上则提供了自助化的操作界面,容许用户通过简略的鼠标勾选数据字段与查问条件,用户通过简略的拖拽便能够疾速实现数据抽取、荡涤转换与加载的加工过程,而且性能十分强悍。 3、办公自动化 很多小伙伴每天都要用EXCEL解决各类报表,比方汇总各类数据,组合排序,跨表关联计算,纠错解决,审核数据等等重复性工作,每天都把大量的工夫花在了收集数据、复制、粘贴、荡涤数据、转换数据这样的事件上了,而不是把工夫花在业务问题的剖析上, 不仅解决效率低下,而且还容易出错。 Smartbi智剖析利用插件的模式,把EXCEL与数据库进行了完满的交融,这个模式摒弃了传统EXCEL手动更新数据源的办法,而是借助云端弱小的性能,间接在EXCEL中调用数据中的字段,无需手动更新数据源便可主动在EXCEL中实现刷新,真正地实现了EXCEL办公自动化。 4、网页端报表传输 对于工作的小伙伴来说,文件传输总是防止不了的,有些EXCEL文件是其余的一些格局或者体积过大,传输起来非常的不不便。这个EXCEL插件在文件互传上具备独特的劣势,只有把做好的报表公布到WEB端,便能够通过链接或者二维码的形式分享给其他人,接管人能够通过PC端和挪动端两种形式对报表进行查阅,这种高效的数据互传形式进步了团队的合作能力,让办公从此变得更加智能。 5、数据安全 随着大数据技术的倒退越来越成熟,数据在每个企业里所表演的角色也变的更加重要,接踵而至的便是数据安全问题,最让泛滥企业谈虎色变的事件便是数据泄露问题了,一不小心便会给企业造成微小的经济损失,因而越来越多的企业开始器重数据的平安问题。这个EXCEL插件的网页端具备欠缺的平安管理体系,它能够管制用户性能权限、数据拜访权限、资源拜访权限,反对按用户、用户组、角色进行治理,反对多套利用零碎共用同一套用户管理系统,反对多级用户管理体系,能够确保企业数据安全无虞。 以上就是利用EXCEL去解决大数据的办法,如果感觉不错的话,能够依照我说的去进行测试,置信会对你的工作效率有很大的晋升。**

March 12, 2021 · 1 min · jiezi

关于excel:EXCEL应用思迈特软件Smartbi数据可视化终极教程

在大数据倒退越来越迅速的时代,很多企业都依赖数据去做决策,在剖析数据时,须要对数据进行提取、加工和报表出现。事实上,制作一份残缺的剖析报表须要具备十分多的常识,除了工具要十分相熟之外,制作图表的思路也须要十分沉闷。图表国外专家Nathan Yau总结了在数据可视化的过程中,个别要经验的四个过程,在这四个过程中都要重复进行考虑: 你领有什么样的数据;你想表白什么样的数据信息;你会什么样的数据可视化办法;你从图表中能取得什么样的数据信息。 依据以上的图片得进去的信息,能够看出数据分析是一个十分系统性的事件,上面将会从数据提取、报表丑化、报表分享这几个方面离开进行赘述。 数据提取 1、数据源 从各种零碎、erp、手工统计后得出的数据,个别通过二维表的模式进行保留,有题目、字段、行这些信息,如果数据源超过百万行的,EXCEL跑不动须要用到数据库的,能够把数据源导进去Smartbi智剖析云平台里,间接在EXCEL里自在拖拽数据字段进行剖析,十分给力。 2、你想表白什么样的数据信息 销售数据:销售额、销售量、指标达成进度、客单价。。。 财务数据:支出、利润、老本、费用摊派、边际奉献。。。 客户满意度:客户投票量、满意度、参评率、客户画像。。。 人力资源:入职报到率、培训期流失率、岗中流失率、岗中淘汰率。。。 3、数据源加工 工夫:提取周、月、季度、年。。。 文本提取:LEFT、RIGHT等函数截取文本个别文字。。。 匹配表:依据其余表格的信息进行匹配,如数据源只有省份信息没有片区信息,须要利用另一份数据进行信息匹配。。。 4、数据提取 利用公式、透视表等形式失去所需的数据,随后便能够对数据进行报表的制作了。透视剖析能够在EXCEL里操作,也能够在高大上的Smartbi智剖析云平台里进行操作: 报表丑化 1、色调 1.1题目的染色 为达到醒目和与表格内容辨别的目标,行题目通常集体喜爱应用深一些的色彩为表头单元格染色,倡议深底白字: 1.2边框的染色 通常边框的色彩抉择倡议以彩色为主: 1.3字体的染色 字体最罕用的是彩色,但有时为了突出重点,为了显示醒目的数字倡议用深红色: 1.4图形的染色 图形的色彩没有特定的要求,能够尝试一些比拟娇艳显眼的色彩,防止用一些比拟爽朗古板的色彩,倡议色彩:绿色、深蓝色、深灰色: 1.4其余 1.41如果没有特殊要求的前提下,色彩能够自在搭配,整洁慷慨即可,然而某些企业有本人的主色调,例如京东是红色,美团是橙色,携程是蓝色,在设计报表的过程中就要以企业的主色调为主,尽量合乎企业外部的审美需要。 1.42色彩抉择能够到中国色网站上进行阅览,该网站有很多酷炫的色彩能够抉择。 1.43色彩的抉择尽量在感官上给他人一种耳目一新的感觉,造成视觉上的抵触,相邻的两个图形之间能够抉择不一样的色彩,版面上也能够尝试多种色调自在搭配,总的准则就是整洁慷慨,色彩鲜明。 2、文字 2.1字体个别失常抉择微软雅黑,无论是表格还是图形上的文字,该字体在很多企业中十分通用,但该字体如果不受权的话则不能用于商用,那么倡议抉择其余收费的字体,例如思源黑体。 2.2字号:题目的大小个别比注释大一号,题目能够抉择10号或者11号字体,注释能够9号或者10号,但不是所有报表都通用,还得依据具体的状况再进行抉择;个别题目或者图形里的文字能够进行加粗,以示醒目: 3、图形 3.1图形抉择:柱形图、饼状图、折线图、雷达图… 比拟图形抉择:柱状图、条形图、折线图、雷达图; 散布图形抉择:直方图、正态分布图、散点图; 形成图形抉择:条形图、饼状图; 分割图形抉择:散点图、气泡图; 选取准则:让他人容易了解、合乎版面布局 3.2图形丑化 字体:倡议微软雅黑,题目14号字体,标签、数字9号字体,可抉择加粗 色彩:显眼醒目即可 数据标签:数据量较少时可全副显示,如果数据量较多则能够不显示 坐标轴:如果数据量较多时,能够暗藏,腾出局部空间 网格线:零碎默认主动显示,如果不须要能够暗藏 背景图:能够应用两种色彩互相进行搭配 坐标轴格局:边界、刻度线、数字等依据理论状况进行调整 3.3个性化图形 如果只应用罕用的图形,会略显枯燥,通常为了使报表更加高大上,会应用一些比拟个性化的图形,互相进行搭配: 4、布局 ...

March 11, 2021 · 1 min · jiezi

关于excel:思迈特软件SmartbiExcel竟可以处理大数据我惊呆了下巴

长期用EXCEL做表格的人都晓得,无奈解决大数据是咱们心中永远的痛,看着他人一个个都用上了PYTHON、数据库等牛逼的工具,工资还比本人高出了不少,本人却只能用着EXCEL以蜗牛般的速度去解决数据,真是恨本人为什么不早点去学习大数据,这样就能够早点升职加薪了。就拿共事小李来说,工作了5年,只会用EXCEL复制粘贴,如果叫他去做好一份超过百万行的数据表格,他非得给你折腾半天不可,真是急死人。 哎,这样的工作效率怎么能行呢。为了进步本人的业务水平,小李到处去打听学习大数据的培训班,并在网上找了一大堆培训资料。其实这些材料在网上很容易找,而且各种大数据的培训广告打得天花乱坠,百度上轻易一搜大数据这个词,就会进去一堆的信息,无非就是PYTHON,数据库这样的课程。小李就开始去学习了,过了几天之后哭着通知我,这些工具真的是太难学了,没有编程根底基本学不进去,问我有没有更加简略的办法。 简略的方法也不是没有,例如云端就是一个很好的办法,把几百万行甚至是几千万的数据量导进去让云端服务器解决,几秒钟就能得出计算结果,比写代码快多了,无疑是最好的抉择。云端这个词可能大家都有听过,例如阿里云,网易云,百度云等等,这些公司都在云端有一个十分弱小的云端数据库,用来专门去做数据存储和数据处理的。云端数据分析也是一样的情理,通过云端弱小的计算能力,能够在十分短的工夫内把一份超大容量的数据实现拆解,无需简单的操作,也不须要写语句,对于不会用数据库或者写代码的人来说,几乎是一个天大的福音。 以我用过的Smartbi大数据分析平台为例,就是用云端解决大数据的最好抉择。这里有两个利用场景能够抉择,第一个是把EXCEL或者CSV文件间接导进去云端,这样的益处就是不必关上EXCEL文件,间接在云端就能够实现透视剖析,如果在电脑里关上一份千万行数据量的EXCEL文件,你的电脑可能会卡死甚至解体。第二个是用Smartbi连贯你本人的数据库,如果你有在用Oracle,Mysql或者其余数据库的话,就能够互相能够建设一个连贯,让你的数据量在云端上进行展现,并得出剖析后果。 用过数据库的人都晓得,用EXCEL连贯数据库是有一点小简单的,会把你折腾半天,然而我用Smartbi连贯数据库的话,只须要几秒钟就行了。连贯好之后,关上一个空白的EXCEL文件,在EXCEL的界面里会呈现一个数据集面板,外面能够找到你保留在云端里的数据。而后通过拉拽的形式,便能够把数据字段拖曳到EXCEL里进行剖析,齐全不须要关上一个超大容量的EXCEL文件。 这样能不能齐全实现报表自动化呢?答案是能够的。因为数据源连贯之后,云端能够实时进行数据更新,只有是数据产生了任何扭转,云端都能够辨认进去。如果须要在本地的数据库追加EXCEL数据,能够在这个界面里抉择增加到已有表,便能够实现追加数据的操作。 解决大数据还得须要一个弱小的仪表盘展现工具,因为数据量太大,你还是用动态报表去做可视化的话,会十分的艰难,因而动静报表是最好的抉择。既能够实现动态数据的展示,又能够实现丰盛的图形成果,是做数据可视化的最佳抉择。以下图为例,EXCEL如果要做出这样的成果恐怕是十分艰难的。 通过以上对大数据概念的诠释,置信你曾经理解了大数据要解决的问题是什么。随着时代的倒退,EXCEL曾经没有方法去为你解决所有的问题,因而把握一门大数据处理的工具是必须要做的事件,这会让你在工作中熟能生巧,得心应手。如果你把这门常识吃透了,置信对于退职场上的你来说无疑是锦上添花,升职加薪更是不可企及。

March 11, 2021 · 1 min · jiezi

关于excel:厌倦了EXCEL想玩点新花样Smartbi教你利用Python做数据筛选

python是一门非常简单和实用的数据分析工具,咱们晓得其实能够利用python对EXCEL数据做简略的筛选。明天咱们利用ETL+Python的搭配组合,对EXCEL数据进行深层次的加工,这一次咱们要做的是高级筛选,请跟着我一起学习吧。 数据源 咱们用电商订单明细表: EXCEL筛选 咱们回顾一下上一篇文章里的数据需要,第一个是依据订单日期筛选2010年的订单,第二个是依据订单等级去筛选高级的订单,这一次咱们把筛选条件进行降级,减少一个条件:在原先两个筛选条件的根底上,筛选出利润金额前10的订单。如果在EXCEL里操作的话,能够利用公式或者本身的筛选性能去实现,然而在python又是怎么实现的呢? 咱们能够在pycharm等软件上写python脚本去实现,然而我举荐大家用Smartbi智剖析的ETL性能去实现,Smartbi智剖析的ETL界面里也提供了python脚本的编写页面,并且很多简略的需要通过ETL就能实现,无需撰写简单的代码,非常适合编程小白。 加载数据 关上Smartbi智剖析里ETL界面,咱们先连贯好数据源,我曾经提前把EXCEL文件导入到了Smartbi智剖析的零碎里,而后把关系数据源拉拽到展示区里,并在左边找到数据源寄存的门路: 加载实现后,咱们能够对数据源进行预览: 条件过滤 当实现了数据连贯后,接下来就能够利用Smartbi智剖析ETL里自带的python脚本对数据进行各种解决,咱们先把python的组件拉拽到两头的展示区,并与下面的关系数据源进行相连: 以下脚本是Smartbi智剖析自带的脚本,曾经提前装置好了pandas和numpy的库,前面的函数也写好了一部分代码,只有依据以下脚本进行扩大,便能够在ETL上利用python进行数据荡涤: 在输出python脚本之前,咱们再明确一下要实现的需要,其中后面两个条件是和上次一样的,咱们无需进行改变,间接复制脚本过去即可,如果不懂的能够查看我前一篇文章。第三个条件须要做的是筛选利润额前10的订单,这里咱们援用pandas中的sort_values函数进行排序,原理相似于SQL中的order by,能够将数据集按照某个字段中的数据进行排序,前面接ascending=False,即对数据进行降序排列,head(10)代表的是取前10的值: 咱们看一下python脚本执行后的成果,年份这一列把2010年给筛选进去了,订单这一列筛选的是高级的订单,订单利润这一列的数据依照降序把前10的数据给筛选进去了: 数据输入 实现python的筛选程序后,咱们把执行筛选后的表格进行保留,能够抉择保留在数据库中,也能够保留在数据集里,这里我仍旧抉择数据集的保留形式,因为不便在EXCEL里进行调用: 回到EXCEL里,点击EXCEL插件里的“视图”,在左边会呈现Smartbi智剖析的数据集面板界面,点击下拉菜单,便能够找到保留在云端的数据集,也能够间接输出文件名进行搜寻: 点击EXCEL工具栏上的“刷新”,数据集里的字段便会显示在EXCEL里,咱们就能够利用这些数据在EXCEL里进行数据分析了:

March 9, 2021 · 1 min · jiezi

关于excel:再见-VBA神器工具统一-Excel-和-Python

大家好,我是东哥。 常常给大家举荐好用的数据分析工具,也收到了铁子们的各种好评。这次也不例外,我要再举荐一个,而且是个爆款神器。 Excel和Jupyter Notebok都是我每天必用的工具,而且两个工具常常协同工作,始终以来工作效率也还算不错。但说切实,毕竟是两个工具,应用的时候必定会有一些切换的老本。 最近,在逛GitHub忽然发现了一款神器「PyXLL-Jupyter」,它能够完满将Jupyter Notebook嵌入到Excel中!是的,你没听错,应用它咱们就可在Excel中运行Jupyter Notebook,调用Python函数,实现数据共享。 一、装置首先,想要在Excel中运行Python代码,须要装置PyXLL插件。PyXLL能够将Python集成到Excel中,用Python代替VBA。 先用 pip 装置 PyXLL。 pip install pyxll而后再用PyXLL独特的命令行工具装置Excel插件。 >> pyxll install装置好了PyXLL在 Excel中的插件,下一步就是装置pyxll-jupyter软件包了。应用pip装置pyxll-jupyter软件包: pip install pyxll-jupyter装置结束后,启动Excel,将在PyXLL选项卡中看到一个新的Jupyter按钮。 单击此按钮可在Excel工作簿的侧面板中关上Jupyter Notebook。该面板是Excel界面的一部分,能够通过拖放操作勾销停泊或停靠在其余地位。 在Jupyter面板中,你能够抉择一个现有的Notebook或创立一个新的Notebook。创立一个新的Notebook,抉择新建按钮,而后抉择Python 3。 二、应用办法这样做有什么用途呢? 1、Excel和Python共享数据比方,咱们要将数据从Excel导入Python。 因为Excel和Python曾经在同一过程中运行了,所以在Python中拜访Excel数据以及在Python和Excel之间切换十分快。 更牛X的是,pyxll-jupyter还独自附带了一些IPython魔法函数,输出后一键即可实现同步。 %xl_get 将Python中的数据移到Excel,也是同理,非常简单。 无论是应用Python先加载数据集,再传输到Excel,还是其它模式,从Python复制数据到Excel非常容易。 %xl_set 当然,%xl_get和%xl_set都附带参数选项能够自定义导入导出规则。 2. 在Excel中应用Python绘图PyXLL的另一大用处就是它集成了简直所有支流的可视化包,因而咱们能够在Excel中利用这些可视化包随便绘图,包含matplotlib、plotly、bokeh和altair等。 %xl_plot 同样,应用魔法函数%xl_plot在Excel中能够绘制任何的Python图。任何一个受反对的可视化包也可进行绘图而后传递图形对象到Excel中,比方上图中应用pandas的绘图成果就很好。 %xl_plot df.plot(kind='scatter')3. 从Excel调用Python函数应用Excel离不开函数,而当咱们须要一些简单性能时,自带函数未必能满足咱们的需要。 通过PyXLL,咱们能够间接在Excel中调用Python函数,并对其进行实时测试。这就防止了Excel和Jupyter之间的来回切换老本,有点像dataframe的apply用法,写个函数间接与Excel完满交融。 函数写好后,还可将其增加到PyXLL Python我的项目中。这样当前每次都能够复用实现雷同性能,几乎不要太香! from pyxll import xl_func@xl_funcdef test_func(a, b, c): return (a * b) + c比方,输出以上代码在Jupyter中运行后,Python函数将立刻可被Excel工作簿调用。 不只是简略的函数,还能够将整个数据作为pandas的DataFrames传给函数,并返回任何的Python类型,比方numpy array、DataFrames,甚至还能够通过给@xl_func装璜器一个签名字符串来通知PyXLL输入什么类型。例如,以下函数: from pyxll import xl_func# 装璜器签名通知 PyXLL 如何转换函数参数和返回的值@xl_func("dataframe df: dataframe<index=True>", auto_resize=True)def df_describe(df): # df 是一个从数据集里创立的 pandas DataFrame 传递给函数 desc = df.describe() # desc 是新的 DataFrame(PyXLL转换为一组值并返回给Excel所创立的) return desc当初能够编写简单的Python函数来进行数据转换和剖析,然而能够协调在Excel中如何调用或排序这些函数。更改输出会导致调用函数,并且计算出的输入会实时更新,这与咱们冀望的一样。 ...

December 31, 2020 · 1 min · jiezi

关于excel:话题热议有没有能替代Excel的数据处理软件

说到数据分析工具,脑海里第一闪现的就是Excel,但你要问我有没有齐全代替Excel的数据处理软件。我只能答复说:有必定是有,然而能不能超过Excel,我不敢打包票(须要大家本人去试用体验过后,能力得出结论,毕竟我一个人说了不算),只能说市场上存在的数据处理软件必定也有其亮点。那么,数据处理软件的亮点是什么?上面给大家简略解说一下。 要想晓得一款数据处理软件能不能超过或代替Excel,首先咱们要理解Excel的次要特点及作用。 一、Exce次要的特点: 1、表格制作:简略的表格录入、制作、丑化。 2、透视表:实现数据透视的成果,能够说学会数据透视表,根本能够解决80%的工作。 3、公式:通过公式能够进行数学计算。 4、统计分析:Excel里的数据分析能够实现描述统计、假设检验、抽样等统计分析的性能,只有用的好,不逊色于业余的统计分析软件。 5、图表:用Excel作图操作简略。简略的日报/月报中以及本人剖析时Excel的图表齐全能够满足咱们的需要。然而当要进行业余的展现时,图表的丑化就显得尤为重要,而用Excel去丑化图表,也不是不行,只是要用到很多偏门的小技巧,没必要花那么多工夫,现成有可用的工具。 6、VBA:还能够用VBA编程实现更高级简单的需要。 7、插件:Excel还能承载很多有用的插件,比方PowerQuery、PowerMap、PowerView等,来辅助咱们实现更为弱小的数据分析性能。 总的来说,Excel能够说是数据分析根底以及必备的工具,在咱们日常办公中,必定少不了要用到Excel。然而Excel尽管有其劣势,但同时也存在有余,不然大家也不会想要找其余的数据处理软件来代替Excel。 二、Excel常见的不足之处: 1、如果是把数据库或其余平台的数据导入到Excel进行剖析时,会很卡。 2、如果存在大量数据时,剖析数据所破费的工夫老本也是很大的,几个小时是常有的事。 3、Excel的学习老本高,很多深层次的性能,咱们本人摸索起来太慢了。 4、数据分析图表不太好看,更确切的说应该是不合乎现代化审美需要。 综合以上几个Excel特点和不足之处。上面咱们来说说数据处理软件的亮点。 三、数据处理软件的亮点介绍! 不晓得大家有没有用过低代码(零代码)开发平台,低代码(零代码)开发目前在国内曾经非常欠缺,它能依据企业需要,低成本高效率的搭建数据处理软件,通过可视化设计器,以拖拽的形式疾速构建应用程序。艰深点讲,就是能够间接点点按钮就能出后果的事件,像很多公司的财务零碎、后勤零碎、数据图表剖析都能够分分钟搭建,而且计算速度十分快。在大量的数据背后也齐全感觉不到卡顿。简单的性能也能迅速上手。数据处理剖析基本上是一键搞定。 目前在用敌人举荐的工具织信集体免费版,刚开始抱着尝试的心理,把excel数据上传到织信数据处理软件上,而后进行剖析,莫名发现不仅不卡,而且做进去的可视化成果还不错。起初发现能够间接对接一些数据源和数据库,果决不去麻烦地传Excel了,而是间接在织信数据处理软件上间接对接须要剖析的数据源了,因为这样数据会每天实时更新,数据就不必传来传去做剖析,每天花点工夫看数据就行了,很省心。 说到数据处理剖析方面,我感觉从某些方面来讲,织信能够成为代替Excel进行图表丑化工作的一个工具。它将数据计算和好看的图表完满地交融在一起,能够在几分钟内生成好看的图表、坐标图、仪表盘与报告。是用来疾速剖析、可视化的弱小工具,偏差商业剖析。 特点: 1、轻松整合,易上手。 2、交互性,相似于Excel数据透视表/图的性能,可进行交互。 3、好看的图表,轻松制作好看的仪表盘、坐标图、甘特图等。 比方我本人做的集体数据处理软件利用,它能够将集体感兴趣的内部数据,批量导入,进行存档,剖析与统计。你所上传的数据能够是:体育赛事数据,历史数据,各种统计数据。反对excel导入,网页内容导入,文本导入等形式。 四、最初论断: 织信数据处理软件是否可能替换Excel?集体认识是:若是大家是想用某个工具搭建多个利用零碎。比方:OA办公、crm客户治理、ERP企业治理、绩效治理、人事管理、数据业务剖析方面。那织信比Excel好用。毕竟能够跨零碎协同操作。 正当并且无效地使用数据处理软件,不仅能够让咱们工作高效地运行,还能最大水平保障工作指标的达成。我举荐应用织信低代码开发平台,它内置了100+的利用模板,笼罩数据图表、我的项目、绩效、人事、企业服务、集体及组织等多个利用场景。领有在线搭建性能,点击一键装置,即可收费试用。5人以下一生收费应用。是帮忙企业开启数字化转型的重要引擎。

December 23, 2020 · 1 min · jiezi

关于excel:辅助-Excel-的数据计算-addins

Excel 中遇到较简单的运算,数据分析师常会用 add-ins 辅助解决。本文考查了一些常见的 add-ins,从部署难度、开发难度、晦涩水平等方面进行深度比照,并着重考查了数据计算能力,esProc 在这些 add-ins 中的体现绝对杰出。点击辅助 Excel 的数据计算 add-ins理解详情。 对于大多数简略运算,Excel都提供了不便的实现伎俩,有时是易用的函数,有时是直观的按钮或菜单。但咱们还是会遇到的一些较简单或非凡的运算,依附Excel自身很难实现。Excel提供了add-in接口,能够通过这个接口执行内部程序,从而借助内部语言或脚本实现这些较简单或非凡的运算,达到辅助Excel的目标。 上面,让咱们深刻理解一些Excel的常见数据计算add-ins,并评估它们的计算能力。 Excel DNAExcel DNA是晚期呈现的一款Excel add-in,它能够把程序员写好的动静库函数放到Excel里应用,动静库能够应用C#/F#/VB.net等语言等编写。 具体用法上,Excel DNA和其余所有add-ins都相似,首先要编写自定义函数。比方上面C#编写的代码中(引自Excel DNA官网),MyFunction是自定义函数名。 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using ExcelDna.Integration; namespace MyLibrary { public class Class1 { \[ExcelFunction(Description="few people use this way!")\] public static string MyFunction(string name) { return "Bonjour" + name; } } } 下面的代码须编译成动静库,之后能力在Excel中应用。 接下来,个别要配置自定义函数和add-in的关系。比方上面的DnaSample.dna文件,表明本add-in的名字是"My name",对应的动静库是Mylibrary.dll(含有多个自定义函数)。 <DnaLibrary Name="My name" RuntimeVersion="v4.0"> <ExternalLibrary Path="Mylibrary.dll" /> </DnaLibary> 最初在Excel中配置该add-in,就能够在单元格中调用MyFunction这个函数了,如下: ...

November 28, 2020 · 2 min · jiezi

关于excel:Excel-文件结构化解析示例

【摘要】 本文介绍如何将各种构造的 Excel 文件解析成结构化数据,如一般行式、简单表头、自在格局、穿插表、奴才表、大文件等,并用 esProc SPL 举例实现。请点击Excel 文件结构化解析示例理解详情 本文将介绍如何进行各种格局的Excel文件结构化解析,如一般行式、简单表头、自在格局、穿插表、奴才表、大文件等,并提供用 esProc SPL 编写的代码示例。esProc 是业余的数据计算引擎,其采纳的 SPL 中有欠缺的 Excel 文件处理函数,进行结构化解析及后续的计算、入库等操作十分不便。 1. 一般行式这是一种最简略的文件格式,文件中每行都是一条数据记录,更常见的是第一行是列题目。 示例:在学生问题文件scores.xlsx中,查问各班语文均匀问题。局部数据如下图: esProc SPL脚本如下: 2. 简单表头少数时候,Excel文件的表头格局并不简略,往往是由多行形成的,比方有表题目、项目名称、填表人、填写日期、页码等信息。解析这种格局的文件时,须要跳过简单的表头,指定从数据行的地位开始读取,而后指定结构化后的数据各列的列名。 示例:在我的项目造价文件itemPrices.xlsx中,计算我的项目总造价,局部数据如下图: esProc SPL脚本如下: 3. 自在格局一条数据记录扩散在多行,字段列值单元格紧跟在列名单元格前面或上面,可能有跨列或跨行的合并单元格。但每条记录所占的行数以及对应行构造是雷同的。循环读取时要以每条记录所占行数为单位组成一条记录。 示例:把自在格局的员工信息文件employee.xlsx存入到数据库表employee中,局部数据如下图: esProc SPL脚本如下: A1创立列名为“ID、Name、Sex、Position、Birthday、Phone、Address、PostCode”的空序表 A2关上Excel数据文件 A3定义雇员信息所在单元格列号序列 B3定义雇员信息所在单元格行号序列 A4用for循环读取每个雇员信息 B4 A3.(~/B3(#))先算出以后雇员单元格编号序列,再读出这些单元格值组成雇员信息序列。第一次循环时为\[C1,C2,F2,C3,C4,D5,C7,C8\],第二次循环时为\[C10,C11,F11,C12,C13,D14,C16,C17\]……每次行号加9。$\\[A2.xlscell(\\]与"A2.xlscell("雷同,都是示意一个字符串,它的益处是在IDE中编写程序时,如果A2单元格的编号产生了变动,$\[A2.xlscell(\]中的A2会主动变动,比方在A2前插入了一行,这个表达式就会变成$\[A3.xlscell(\],而用引号的话,就不会主动变了。 B5判断雇员ID值是否为空,为空则退出循环,完结读数 B6将一条雇员信息存入A1序表尾 B7让雇员信息的行号序列都加上9,读取下一条雇员信息 A8-A10连贯数据库,将雇员信息存入数据库表employee,敞开数据库 读取进去的A1单元格数据如下图所示: 4. 穿插表穿插表是统计学中常见的一种矩阵式表格,能够清晰地表白两个变量间的数量关系。穿插表数据逐行读入后,须要以某个列变量为基准,另一个变量及穿插值进行行转置;或者以某个行变量为基准,另一个变量及穿插值进行列转置。 示例:将订单地区与货运形式穿插表cross.xlsx文件解析成结构化数据,文件数据如下图所示。 esProc SPL脚本如下: A3格的局部数据如下图所示: 5. 奴才表每个sheet是一条主表记录,同时sheet中也蕴含N条子表记录。文件中有多少主表记录,就有多少个sheet。对这种奴才表构造的数据,须要创立两个数据表别离保留主表和子表的记录。 示例:在员工信息登记表文件staff.xlsx中,每个sheet有员工信息及他的家庭成员信息,请将员工信息及家庭成员信息别离解析成两个结构化数据表。其中一个sheet如下图: esProc SPL脚本如下: ...

November 28, 2020 · 1 min · jiezi

关于excel:生成各种格式的-Excel-文件示例

【摘要】本文介绍如何将经各种渠道得来的结构化数据主动生成各种格局的 Excel 文件,如单纯导出数据、导出大量数据、指定显示属性、固定行列填充、动静条件显示属性、分组带明细及统计、穿插统计表等,并用 esProc SPL 举例实现。请点击 生成各种格局的 Excel 文件示例 理解详情 在数据处理时,有时要把查问、剖析计算、统计、数据采样等各种渠道得来的结构化数据,用程序主动生成各种格局的Excel文件。 本文将别离针对单纯导出数据、导出大量数据、指定显示属性、固定行列填充、动静条件显示属性、分组带明细及统计、穿插统计表等介绍实现办法,并提供用 esProc SPL 编写的代码示例。esProc 是业余的数据计算引擎, SPL 中有欠缺的 Excel 文件导出函数,将结构化数据导出成 Excel 十分不便。本文不探讨要导出的数据如何得来,假如它曾经存在一个文本文件里了。 1. 单纯导出数据1.1 导出新文件将列名导出到Excel文件的第一行,第二行开始导出数据记录,每行一条记录。 示例:将订单表数据导出到一个新的Excel文件orders.xlsx,esProc SPL脚本如下: 导出时如果文件不存在,会主动创立文件。函数xlsexport的参数中,能够指定须要导出的列,本例中没有指定,则导出所有的列;还能够指定导出数据的sheet名字,本例没有指定,则导出到第一个sheet中。 导出后的orders.xlsx局部数据如下图所示: 1.2 追加数据Excel文件曾经存在,要将新的数据追加在已有数据的前面。此时只须要追加数据记录,不必再导出列名了。 示例:将今日新减少的订单表数据追加到原有的orders.xlsx中,esProc SPL脚本如下: 1.3 导出到指定 Sheet导出数据时,指定保留数据的Sheet的名称。 示例:将来自Shantai公司的订单表数据导出到orders.xlsx文件里名为Shantai的Sheet中。本例中只导出指定的列数据,并批改某些列名,esProc SPL脚本如下: 导出后的orders.xlsx局部数据如下图所示: 2. 导出大量数据当有大量的、不能一次性全副载入内存的数据须要导出时,要用游标分批读入数据,再用流的形式将数据写入OpenXml格局(即扩大名为xlsx)的Excel文件,只需占据大量内存。Excel限度一个sheet最多只能寄存1048576行数据,所以当导出数据行数超过此限度时,咱们须要新减少一个sheet来保留。 示例:将大数据订单表导出到big.xlsx文件中,esProc SPL脚本如下: 导出后的big.xlsx最初几行数据如下图所示: 本例中导出了123663条数据记录,其实用这种形式能够导出任意条记录(不过得保障硬盘存储空间短缺)。 3. 指定显示属性除了间接导出数据,有时还心愿生成的excel文件可能显示得比拟好看,比方能够指定字体、色彩、背景色、对齐形式、显示格局等。这时须要事后建好这个excel文件(模板),定义好须要的这些显示属性,而后再向这个文件中导出数据,定义好的显示属性就会随之出现。 示例:把订单表数据导入到orders.xlsx中,并按如下图所示格局显示: 本例将多种预约义显示属性都集中在一起作示范,显示比拟芜杂,仅仅为了演示性能,没有从好看上登程去设计。esProc SPL脚本与1.1节雷同。 导出后的Excel文件如下图所示: 4. 固定行列填充有一个行列数和单元格格局都固定的Excel文件,外面有些空单元格,须要把相干数据填写到这些格子里,这要求提供往单个单元格填写数据的性能。在数据填报业务中会常常用到。 示例:某基金公司总公司向分公司下发了一张excel表格,要求分公司填入它的相干数据后回传给总公司,下发的excel文件如下: esProc SPL脚本如下: ...

November 28, 2020 · 1 min · jiezi

关于excel:esProc-利用剪贴板强化-Excel-计算

遇到 Excel 难以实现的简单或非凡运算时,可先用剪贴板将数据复制到 esProc,利用 esProc 弱小的计算能力实现,这种形式比 add-ins 有更多长处,具体场景和代码解析请点击esProc 利用剪贴板强化 Excel 计算 遇到Excel难以实现的简单或非凡运算时,可先用剪贴板将数据复制到esProc,利用esProc弱小的计算能力实现,再用剪贴板返回Excel。剪贴板形式比传统的add-ins形式部署更简略,操作更顺滑,开发时不影响剪贴板失常应用,且反对多个源片区和后果片区。 根本用法esProc提供了函数clipboard,可实现剪贴板的根本用法。上面用“各科前3名的学生”为例进行阐明。 Excel中解决前的数据如下,其中A列是学生姓名,B-D列别离是数学、英语、物理问题。 计算指标:求出每学科问题前3名的学生,并追加到本科目问题之后。 这个计算指标须要用到记录汇合TopN、按序号拼接等性能,Excel自身不好实现,但借助esProc就容易多了。先在Excel中选中源片区(A1:D10),按下ctrl+C,复制到零碎剪贴板,关上集算器IDE,编写并执行如下脚本: 下面代码中,clipboard函数有两种状态,其中无参数调用该函数时,可返回剪贴中的字符串,如A1格;以变量或格名为参数调用该函数时,可向剪贴板写入字符串,形如A6中的clipboard(var)。 执行上述脚本后,在Excel的B11格用ctrl+V,即可将剪切板中的数据复制到B11-D13,如下: 随便编辑脚本然而,咱们在编辑调试脚本时,保不齐会用一下复制粘贴,这时候就把剪贴板的内容冲掉了,再执行clipboard()时, 返回的内容就是方才编辑的代码,这样就无奈实现计算了,只能再回到Excel去从新复制,有点麻烦。 针对这个问题,esProc提供了clipboard@e()函数,选项@e示意始终返回第一次从Excel复制到剪贴板中的数据。上面让咱们试一下。 在“各科前3名的学生”这个例子中,假如咱们曾经从Excel复制了数据,并写完了脚本。此时编辑脚本,将A3、A4挪动到B2、B3,再执行脚本时,就会因为A1中的clipbaord()取到谬误数据,而导致A2报错。当初批改代码,在A1应用方才提到的clipboard@e(),则挪动代码后可正确执行。编辑后的代码如下: 多个后果片区clipboard(…)只能返回一个后果,但有些较简单的运算可能须要返回多个后果,这该怎么办呢? 其实 ,在esProc的结果显示区能够间接把多个格值(或变量值)别离复制到剪贴板,并顺次返回Excel。 上面用 “各科前3名和每个人的超过指标”为例进行阐明。 计算指标:在学生成绩单的根底上,不仅在各科目上面追加本科目前3名的学生,而且须要新加一列target,计算出比自己总分略高的3名学生的名单列表,作为自己该当超过的指标。留神,有些人的超过指标有余3人,每个超过指标之间须用>号连贯。 先在Excel中选中源片区(A1:D10),按下ctrl+C,复制到零碎剪贴板,关上esProc IDE,编写并执行如下脚本: 上述代码中,A3存储后果片区1,即本科目前3名的学生;A4存储后果片区2,即每个人的超过指标。另外该当留神到,代码中毋庸export()和clipboard(…)。 上面将计算结果返回Excel。先点击片区1,再点击右侧对应的“copy data”按钮,如下图: 在Excel 的B11 格用ctrl+V ,即可将片区1 复制到B11-D13 ,如下: 再点击脚本中的片区2,按住shift的同时,点击右侧对应的“copy data”按钮,之后在Excel的的E1格按下ctrl+V,即可将片区2连带列名复制到E1:E10。如下所示: 在上述操作中,咱们可通过shift管制计算结果是否带列名,这是esProc的独有形式,其余计算工具不具备此项性能。 多个源片区解决了多指标的问题后,咱们很容易联想到有多个源的问题。计算可能须要应用Excel的多个源片区,但clipboard只能放弃最新复制的那一片,这又该怎么办? 有方法,能够把剪贴板内容间接简单到格子外面去。 上面用 “查问合乎指定条件的订单”为例进行阐明。 Excel中有两个sheet,订单明细和员工名单,其中订单明细如下: 员工名单如下: 计算指标:查问出最近days天内或订单属于部门列表depts的数据,须要的列有订单编号、日期、金额、销售员名字、部门名称。其中days是内部参数,每次执行时都能够输出不同的值,比方输出30示意查问30天内的订单;depts也是内部参数,比方["Markeding","Finance"]。这个计算指标波及动静查问和多键值查问,Excel自身不好实现,但借助esProc就容易多了。 首先,在Excel中选定片区“订单明细”,连带列名一起复制粘贴到esProc脚本的A1单元格;同样地,将片区“员工名单”复制到esProc脚本的A1单元格。如下图: 留神,肯定要进入A1格的编辑状态能力进行复制,不然会把剪贴板的内容填进一大片格子,后果可能变成这样: 这就不好了,占有区域太大,会影响代码布局。 如果操作正确,A1/A2分外观上只出现很小一部分数据,点击后才会出现残缺数据,这是网格局代码的独特之处,适宜在不影响浏览和代码布局的状况下复制大片数据。 复制完两个源片区后,持续编写脚本,期间可屡次运行脚本,可手工操作剪贴板。最初代码如下: ...

October 14, 2020 · 1 min · jiezi

关于excel:Looking-for-the-Best-Excel-Addins

Data analysts often turn to add-ins when they encounter complicated computations in Excel. Here we examine and compare some common add-ins in terms of deployment process, development efficiency, application fluidity and, particularly, computational capabilities. esProc shows more excellent performance than others. Looking Looking for the Best Excel Add-ins for details. Excel provides convenient methods, including easy to use functions and intuitive buttons and menus, for performing simple computations. But it’s hard for it alone to accomplish complicated computations and certain special ones. So it offers the add-in interface through which an external application can be connected to use their language or script to help Excel handle those computations. ...

September 4, 2020 · 9 min · jiezi

关于excel:把-Excel-透视表搬到-WEB-上

【摘要】 Excel 透视表 - 只有遇见就未曾遗记!依据原始数据勾勾选项拖拖拽拽,剖析数据嗖一下就进去了,这么好用的货色怎么能移到 WEB 上呢?去乾学院看个到底:把 Excel 透视表搬到 WEB 上! 提起 Excel 肯定都不生疏,尤其是外面的数据透视表,对于须要进行聚合剖析的状况,依据原始数据勾勾选选就能实现,用起来是倍儿爽吧。 那么,操作起来这么省心的性能要是能移到 WEB 上,嵌入俺的应用程序里,是不是就完满了?so easy! 雷锋同志马上来教你做这事儿。 配角退场——润乾报表多维分析! 上面就先以 Excel 文件作为数据源,与各位小伙伴分享一下多维分析的利用案例,欢送各位热烈围观,优雅吐槽: Excel 文件内容为如下: 这个格局很一般,第一行是题目,前面就是一行行的数据了。 不论这个 Excel 数据文件是在服务器上还是在本地,润乾多维分析界面都能帮你轻松搞定!话不多说,间接看步骤: 关上润乾报表多维分析界面: 点击菜单中的【数据文件】按钮,弹出【关上数据文件】窗口,抉择数据文件。 对于本地文件, 能够点击【关上本地】按钮,找到并应用保留在本地任意地位的数据文件。 对于服务器文件, 能够点击【关上服务器文件】按钮,关上位于服务器指定目录下的所有数据文件。这个目录门路要在 "[demo 利用根目录]/raqsoft/guide/jsp/olap.jsp" 中增加 JS API 进行指定,如下图所示。 抉择好数据文件后,数据集就创立实现了,多维分析最重要的一步也就 ok 了。 接下来就是业务人员自在驰骋的工夫了,随便在简单条件中拖拽表头和指标,想查什么查什么,想算什么算什么。数据透视表中能做的,俺们的 WEB 应用程序也一样能做啦。哈哈,从单机利用一步跃升 Web 环境是不是更爽了! 除了上述所说的通过页面菜单导入数据文件的办法外,还有一种更简略的用法,只有在 URL 里把要剖析的数据文件传进来就能够。比方把 data.xls 放到 "【Web 利用根目录】 WEB-INF\files\fileData\" 目录下,拜访剖析页面时间接在前面追加上文件名就能够了。如:…\raqsoft\guide\jsp\olap.jsp?dataFile=【Web 利用根目录】 WEB-INF\files\fileData\data.xls。 ...

July 24, 2020 · 1 min · jiezi

关于excel:把-Excel-透视表搬到-WEB-上

【摘要】 Excel 透视表 - 只有遇见就未曾遗记!依据原始数据勾勾选项拖拖拽拽,剖析数据嗖一下就进去了,这么好用的货色怎么能移到 WEB 上呢?去乾学院看个到底:把 Excel 透视表搬到 WEB 上! 提起 Excel 肯定都不生疏,尤其是外面的数据透视表,对于须要进行聚合剖析的状况,依据原始数据勾勾选选就能实现,用起来是倍儿爽吧。 那么,操作起来这么省心的性能要是能移到 WEB 上,嵌入俺的应用程序里,是不是就完满了?so easy! 雷锋同志马上来教你做这事儿。 配角退场——润乾报表多维分析! 上面就先以 Excel 文件作为数据源,与各位小伙伴分享一下多维分析的利用案例,欢送各位热烈围观,优雅吐槽: Excel 文件内容为如下: 这个格局很一般,第一行是题目,前面就是一行行的数据了。 不论这个 Excel 数据文件是在服务器上还是在本地,润乾多维分析界面都能帮你轻松搞定!话不多说,间接看步骤: 关上润乾报表多维分析界面: 点击菜单中的【数据文件】按钮,弹出【关上数据文件】窗口,抉择数据文件。 对于本地文件, 能够点击【关上本地】按钮,找到并应用保留在本地任意地位的数据文件。 对于服务器文件, 能够点击【关上服务器文件】按钮,关上位于服务器指定目录下的所有数据文件。这个目录门路要在 "[demo 利用根目录]/raqsoft/guide/jsp/olap.jsp" 中增加 JS API 进行指定,如下图所示。 抉择好数据文件后,数据集就创立实现了,多维分析最重要的一步也就 ok 了。 接下来就是业务人员自在驰骋的工夫了,随便在简单条件中拖拽表头和指标,想查什么查什么,想算什么算什么。数据透视表中能做的,俺们的 WEB 应用程序也一样能做啦。哈哈,从单机利用一步跃升 Web 环境是不是更爽了! 除了上述所说的通过页面菜单导入数据文件的办法外,还有一种更简略的用法,只有在 URL 里把要剖析的数据文件传进来就能够。比方把 data.xls 放到 "【Web 利用根目录】 WEB-INF\files\fileData\" 目录下,拜访剖析页面时间接在前面追加上文件名就能够了。如:…\raqsoft\guide\jsp\olap.jsp?dataFile=【Web 利用根目录】 WEB-INF\files\fileData\data.xls。 ...

July 24, 2020 · 1 min · jiezi

openpyxl给excel填充颜色

需求介绍本人的excel数据是之前通过pandas导出的,现在有个需求就是对excel某一列的每个单元格的值进行判断,如果这个值在某一区间内,那么就给这个单元格填充响应的背景颜色。在使用pandas的过程中发现pandas好像并不能实现此功能,所以在假期期间学习了一下openpyxl,使用它操作excel真是太爽了。数据形式 代码from openpyxl import load_workbookfrom openpyxl.styles import PatternFillwb = load_workbook("airquality.xlsx")# 默认选择第一张sheet表ws = wb.active# 选取数据区cells = ws.iter_rows(min_row=2, min_col=6, max_col=6)# 构建颜色对象,start_color表示前景色,end_color表示背景色。green_fill = PatternFill("solid", start_color='00E400')yellow_fill = PatternFill("solid", start_color='FFFF00')orange_fill = PatternFill('solid', start_color='FF7E00')red_fill = PatternFill('solid', start_color='FF0000')pink_fill = PatternFill('solid', start_color='99004C')maroon_fill = PatternFill('solid', start_color='7E0023')for i in cells: # 每行的内容是元组,每个元组只有一个单元格,所以取第一项的value,然后转为int型 value = int(i[0].value) if value <= 50: i[0].fill = green_fill elif 50 < value <= 150: i[0].fill = yellow_fill elif 150 < value <= 200: i[0].fill = orange_fill elif 200 < value <= 250: i[0].fill = pink_fill else: i[0].fill = maroon_fillwb.save("new_sheet.xlsx")wb.close()最后处理过后的excel为这个样子。 ...

June 25, 2020 · 1 min · jiezi

PHP-高性能-Excel-扩展-127-发布

为什么使用 php-ext-excel-exportxlswriter是一个PHP C扩展,可用于在Excel 2007+ XLSX文件中写入多个工作表的文本,数字,公式和超链接。 它支持以下功能:100%兼容的Excel XLSX文件完整的Excel格式合并单元格自动筛选图表数据验证和下拉列表工作表PNG / JPEG图像用于写入大文件的内存优化模式适用于Linux,FreeBSD,OpenBSD,OS X,Windows编译为32位和64位FreeBSD许可证唯一的依赖是zlib 基准测试测试环境: Macbook Pro 13 inchIntel Core i516GB 2133MHz LPDDR3 Memory128GB SSD Storage.导出两种内存模式,导出100W行数据,单行27列,每个单元格19个中文字符常规模式: 耗时 29S,内存占用 2083MB;固定内存模式: 耗时 52S, 内存占用 <1MB;读取读取 100W 行数据,每行1列,单元格数据为int全量读取: 耗时 3S, 内存占用 558MB;游标读取: 耗时 2.8S, 内存占用 <1MB;仓库地址Github:https://github.com/viest/php-ext-excel-export Gitee:https://gitee.com/viest/php-ext-xlswriter PECL:https://pecl.php.net/package/xlswriter 文档https://xlswriter-docs.viest.me End最后的最后请不要忘记star

September 10, 2019 · 1 min · jiezi

Excel导入导出工具简单好用且轻量级的海量Excel文件导入导出解决方案

Excel导入导出工具项目地址:https://gitee.com/sanri/sanri-excel-poi优点:简单的配置即可实现导出精美的 Excel 表格,可以不用配置来导入一列数据,导入 map 数据,简单配置可以导入实体数据。解决了一些常见问题,比如 导入的时候空行问题导入数据去前后空格继承类也可以导出数据完美的支持日期格式的导入导出数字为浮点型的精度处理完美解决导出时的中文列宽问题可自定义列的顺序支持 Excel 公式发现BUG可以提Issue,可以给我发邮件,可以加我QQ,可以进9420技术群讨论. 作者QQ: 2441719087 作者邮箱: ningxiangsanri@163.com 9420 技术交流群: 645576465 作者微信:sanri1993- 如何使用以后会上传中央仓库,引用 maven 地址为 <dependency> <groupId>com.sanri.excel</groupId> <artifactId>sanri-excel-poi</artifactId> <version>1.0-RELEASE</version></dependency>目前需要自己下载代码来构建,或下载已经构建好的 release 包 : https://gitee.com/sanri/sanri-excel-poi/repository/archive/v1.0-RELEASE?format=zip 还需要添加第三方依赖,如果项目中已经存在依赖,请忽略。(真实项目一般都是有依赖的)<!-- Excel poi --><dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.10-FINAL</version></dependency><dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.10-FINAL</version></dependency><!--apache commons --><dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.8.1</version></dependency><dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version></dependency><dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-csv</artifactId> <version>1.2</version></dependency><!-- slf4j --><dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version></dependency><dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.21</version></dependency>定义实体类@ExcelExport@ExcelImport(startRow = 1)@Datapublic class Simple { @ExcelColumn(value = "年龄",order = 2) private int age; @ExcelColumn(value = "级别",order = 1) private Integer level; @ExcelColumn(value = "姓名",order = 0,chineseWidth = true) private String name; @ExcelColumn(value = "生日",order = 3) private Date birthday; @ExcelColumn(value = "序号",order = 4,hidden = true) private long id; @ExcelColumn(value = "是否成功",order = 5) private boolean success; @ExcelColumn(value = "薪水",order = 6,precision = 2) private double money; @ExcelColumn(value = "奖金",order = 7,precision = 2) private float comm;}获取数据并导出实测在 i5 3 代 cpu ,8 G 内存,导出 10 万数据,用时 5 秒 ...

September 8, 2019 · 2 min · jiezi

仿Excel-React-hook-文章待续

Excel Editor 实现 (Virtual Table 部分)该小项目已经初步完成,写该文章是来练习写文章的。 目前文章进度较慢。 技术栈react (hooks)typescript项目及微软ExcelOnline喜欢就给上star吧 小项目演示地址 小项目Github地址 Microsoft Excel online 背景面试需要做一个小项目,下面是该项目的题目: 使用 TypeScript 开发一个简易版的 Excel WebApp,实现 column & row sort,cell edit,cell calculate 等,可以定义该 MVP 功能集。可以不借助框架或者使用主流框架问题Typescript 以前有了解,但是是第一次使用,简单的使用应该不成问题。Excel 是要实现到何种程度?功能实现,排序,编辑好说,计算这一个是要实现与Excel相同的函数功能么?框架还是要用的,毕竟时间有限这里准备直接使用create react app来开始项目思考从上面总结的问题只有两个地方比较不确认。 描述中提到了Excel, Excel只是表格,如果只是做成简单的表格恐怕不能得到太多的关注,这里决定做出与Excel一样的VirtualTable功能基于上面的virtualtable,实现排序编辑和计算的功能。基本的方向定了后便是整个实现步骤 基本的virtualtable实现选区功能的实现基于选区功能的其它功能实现(设计成插件方式,各个功能独立分隔)

September 7, 2019 · 1 min · jiezi

INDEX与MATCH的结合使用

在对数据做处理时,我们不免会需要使用到查找数据这个功能,比较常用的是excel中的vlookup函数,除此之外,index和match的结合使用也较常被使用到,本文主要介绍index与match的结合使用方法。一、match的使用1、实现功能:返回查找数据的位置(行或列)。2、语法结构:=match(lookup_value,lookup_array,match_type)。3、参数解释:1)lookup_value是需要查找的数据,即目标值;2)lookup_array是查找的范围,即目标区域;3)match_type是可选参数,0、-1、1三种。 4、举例说明:1)参数为0时,lookup_array数据无需按照固定的顺序。2)参数为1时,lookup_array数据需按照升序排列,返回小于或等于目标值的最大值的位置。3)参数为-1时,lookup_array数据需按照降序排列,返回大于或等于目标值的最小值的位置。 二、index的使用1、实现功能:返回指定位置对应的数据。2、语法结构:=index(array,row_num,column_num)3、参数解释:1)array是查找数据的范围;2)row_num是查找数据对应的行;3)column_num是查找数据对应的列。三、match与index的结合使用案例

July 16, 2019 · 1 min · jiezi

php-使用phpofficephpspreadsheet拓展操作excel

一:安装phpoffice/phpspreadsheet composer require phpoffice/phpspreadsheet二:phpoffice/phpspreadsheet API接口详解 PhpSpreadsheet提供了丰富的API接口,可以设置诸多单元格以及文档属性,包括样式、图片、日期、函数等等诸多应用,总之你想要什么样的Excel表格,PhpSpreadsheet都能做到 在使用phpoffice/phpspreadsheet的API接口前,确保引入了正确的文件并实例化 use PhpOffice\PhpSpreadsheet\Spreadsheet;//引入文件$spreadsheet = new PhpOffice\PhpSpreadsheet\Spreadsheet();//创建一个新的excel文档$sheet = $spreadsheet->getActiveSheet();//获取当前操作sheet的对象1:设置字体: $sheet->getStyle('A7:B7')->getFont()->setBold(true)->setName('Arial') ->setSize(10);//将A7至B7两单元格设置为粗体字,Arial字体,10号字$sheet->getStyle('B1')->getFont()->setBold(true);//将B1单元格设置为粗体字2:设置颜色 $sheet->getStyle('A1')->getFont()->getColor()->setARGB(\PhpOffice\PhpSpreadsheet\Style\Color::COLOR_RED);//将A1单元格文字颜色设为红色3:设置列宽 $sheet->getColumnDimension('A')->setWidth(20);//将A列的宽度设为20(字符)$sheet->getColumnDimension('B')->setAutoSize(true);//将B列的宽度设为自动宽度$sheet->getDefaultColumnDimension()->setWidth(12);//设置默认列宽为124:设置行高 $sheet->getRowDimension('10')->setRowHeight(100);//将第十行的高度设为100pt$sheet->getDefaultRowDimension()->setRowHeight(15);//设置默认行高为155:对齐 $sheet->getStyle('A:D')->getAlignment() ->setVertical(\PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER) //设置垂直居中 ->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER) //设置水平居中 ->setWrapText(true); //设置自动换行6:合并单元格 $sheet->mergeCells('A1:D2');//A1到D2合并为一个单元格7:将合并后的单元格拆分 $sheet->unmergeCells('A1:D2');//将合并后的单元格拆分。8:使用applyFromArray实现单元格样式设置 //样式变量$style = [//设置字体样式'font' => [ 'name' => 'Arial', 'bold' => true, 'italic' => false, 'underline' => Font::UNDERLINE_DOUBLE, 'strikethrough' => false, 'color' => [ 'rgb' => '808080' ] ],//设置边框线样式'borders' => [ //allBorders所有的边框线样式 //左边框线 'bottom' => [ 'borderStyle' => Border::BORDER_DASHDOT, 'color' => [ 'rgb' => '808080' ] ], //上边框线 'top' => [ 'borderStyle' => Border::BORDER_DASHDOT, 'color' => [ 'rgb' => '808080' ] ]],//对齐样式'alignment' => [ 'horizontal' => Alignment::HORIZONTAL_CENTER, 'vertical' => Alignment::VERTICAL_CENTER, 'wrapText' => true,],//是否使用前缀'quotePrefix' => true];$sheet->getStyle('A1:D1')->applyFromArray($style);9:设置工作表标题 ...

July 15, 2019 · 3 min · jiezi

使用-SpreadJS-实现-JavaScript-中导入和导出Excel文件

JavaScript是一个涵盖多种框架、直译式、可以轻松自定义客户端的脚本语言,在 Web 应用程序中,更加易于编码和维护。而Excel 作为一款深受用户喜爱的电子表格工具,借助其直观的界面、出色的计算性能和图表工具,已经成为数据统计领域不可或缺的软件之一。 如果有一款产品,能够将二者完美融合,将在前端表格数据处理、数据填报、数据可视化、在线文档等领域大放异彩。SpreadJS,正是这样一款功能布局与Excel高度类似,无需大量代码开发和测试即可实现数据展示、前端 Excel 导入导出、图表面板、数据绑定等业务场景的纯前端表格控件。 使用JavaScript实现 Excel 的导入和导出通过纯JavaScript,您完全可以实现导入和导出Excel文件功能,并为最终用户提供与这些文件进行I/O交互的界面。在本篇教程中,我将向您展示如何借助SpreadJS,在JavaScript中轻松实现导入和导出Excel文件的操作,以及将SpreadJS组件添加到HTML页面是多么的容易。 工欲善其事,必先利其器请下载SpreadJS 纯前端表格控件,以便同步体验设置JavaScript的电子表格项目创建一个新的HTML页面并添加对SpreadJS下载包中Spread.Sheets脚本和CSS文件的引用: <!DOCTYPE html> <html> <head> <title>SpreadJS ExcelIO</title> <script src="http://code.jquery.com/jquery-2.1.3.min.js" type="text/javascript"></script> <script src="http://code.jquery.com/ui/1.11.4/jquery-ui.min.js" type="text/javascript"></script> <link href="http://cdn.grapecity.com/spreadjs/hosted/css/gc.spread.sheets.excel2013white.10.1.0.css" rel="stylesheet" type="text/css" /> <script type="text/javascript" src="http://cdn.grapecity.com/spreadjs/hosted/scripts/gc.spread.sheets.all.10.1.0.min.js"></script> <script type="text/javascript" src="http://cdn.grapecity.com/spreadjs/hosted/scripts/interop/gc.spread.excelio.10.1.0.min.js"></script> </head> <body> <div id="ss" style="height:600px ; width :100%; "></div> </body> </html> 然后在初始化Spread.Sheets组件的页面中添加一个脚本,并使用div元素来包含它(因为SpreadJS电子表格组件使用了Canvas 绘制界面,所以这是初始化组件所必需的一步): <script type="text/javascript"> $(document).ready(function () { var workbook = new GC.Spread.Sheets.Workbook(document.getElementById("ss")); }); </script> </head> <body> <div id="ss" style="height:600px ; width :100%; "></div> </body> 添加Excel导入代码我们需要创建一个客户端ExcelIO组件的实例,并用它来实际打开 Excel 文件: var excelIO = new GC.Spread.Excel.IO(); 然后我们需要添加一个导入文件的函数。在此示例中,我们导入本地文件,但您可以对服务器上的文件执行相同的操作。如果要从服务器端导入文件,则需要引用该位置。以下是输入元素的示例,用户可以在其中输入文件的位置: <input type="text" id="importUrl" value="http://www.testwebsite.com/files/TestExcel.xlsx" style="width:300px" /> 完成上述步骤后,您可以直接在脚本代码中访问该值: ...

July 5, 2019 · 2 min · jiezi

Excelize发布201版本Go语言Excel文档基础库

Excelize 是 Go 语言编写的用于操作 Office Excel 文档类库,基于 ECMA-376 Office OpenXML 标准。可以使用它来读取、写入由 Microsoft Excel™ 2007 及以上版本创建的 XLSX 文档。相比较其他的开源类库,Excelize 支持写入原本带有图片(表)、透视表和切片器等复杂样式的文档,还支持向 Excel 文档中插入图片与图表,并且在保存后不会丢失文档原有样式,可以应用于各类报表系统中。 GitHub: github.com/360EntSecGroup-Skylar/excelize 2019年7月1日,社区正式发布了 2.0.1 版本,该版本包含了多项新增功能、错误修复和兼容性提升优化。下面是有关该版本更新内容的摘要,完整的更改列表可查看 change log。 Release Notes此版本中最显著的变化包括: 新增功能新增 SetHeaderFooter() 方法,支持设置页眉和页脚,相关 issue #394新增 SetColStyle() 方法,支持设置列样式,相关 issue #397新增 SetDefaultFont() 和 GetDefaultFont() 方法,支持设置工作簿默认字体,相关 issue #390新增 SetDocProps() 和 GetDocProps() 方法,支持设置和获取文档属性,相关 issue #415函数 AddChart() 新增加了 26 种图表的创建:簇状圆锥、堆积圆锥、百分比堆积圆锥、三维圆锥图、簇状水平圆锥图、堆积水平圆锥图、堆积百分比水平圆锥图、簇状棱锥图、堆积棱锥、百分比堆积棱锥、三维棱锥图、簇状水平棱锥图、堆积水平棱锥图、堆积百分比水平棱锥图、簇状柱形图 、堆积柱形图、百分比堆积柱形图、三维柱形图、簇状水平圆柱图、堆积水平圆柱图、堆积百分比水平圆柱图、三维曲面图、俯视框架曲面图、三维曲面框架图、气泡图与三维气泡图,不受支持的图表类型将返回错误提示新增 SetDefinedName() 和 GetDefinedName() 方法,支持设置和获取名称优化并明确了打开加密文件时的错误提示信息函数 AddPicture() 现在支持添加 TIF 和 TIFF 格式的图片问题修复修复当数据验证公式中存在双引号时产生的问题修复内部计数错误导致的部分情况下产生重复批注问题,相关 issue #373修复部分情况下因读取内部工作表 map 错误导致读取文件失败的问题,相关 issue #404提升了处理包含数据透视表的文档兼容性,相关 issue #413提升了字号与粗体样式的兼容性,相关 issue #411、#420 和 #425优化内部重算组件以修复部分情况下在工作表中删除或插入行造成文档损坏的问题,相关 issue #421 和 #424修复部分情况下隐藏工作表失效的问题,相关 issue #418修复内部主题颜色索引溢出导致部分情况下图表系列过多导致文档损坏的问题,相关 issue #422其他完善单元测试提升覆盖度,行覆盖度达到 96.05%代码优化,修复 golint 问题

July 1, 2019 · 1 min · jiezi

阿里-EasyExcel-7-行代码优雅地实现-Excel-文件生成下载功能

欢迎关注个人微信公众号: 小哈学Java, 文末分享阿里 P8 高级架构师吐血总结的 《Java 核心知识整理&面试.pdf》资源链接!!个人网站: https://www.exception.site/essay/how-to-create-excel-by-seven-line-code 目录一、前言二、Apache poi、jxl 的缺陷三、阿里出品的 EasyExcel,安利一波四、EasyExcel 解决了什么五、快速上手六、特殊场景支持七、Web 下载示例代码八、需要注意的点九、总结一、前言关于导出 Excel 文件,可以说是大多数服务中都需要集成的功能。那么,要如何优雅快速地(偷懒地)去实现这个功能呢? 你可能第一想法是:这还不简单?用 Apache 开源框架 poi, 或者 jxl 都可以实现啊。面向百度编程,把代码模板 copy 下来,根据自己的业务再改改,能有多难? 嗯.. 的确不难,但是你的代码可能是下面这个熊样子的: 上面这段代码看上去是不是又臭又长呢?今天,小哈将教您如何使用 7 行代码搞定 Excel 文件生成功能! 二、Apache poi、jxl 的缺陷在说如何实现之前,我们先来讨论一下传统 Excel 框架的不足!除了上面说的,Apache poi、jxl 都存在生成 excel 文件不够简单优雅快速外,它们都还存在一个严重的问题,那就是非常耗内存,严重时会导致内存溢出。 POI 虽然目前来说,是 excel 解析框架中被使用最广泛的,但这个框架并不完美。 为什么这么说呢? 开发者们大部分使用 POI,都是使用其 userModel 模式。而 userModel 的好处是上手容易使用简单,随便拷贝个代码跑一下,剩下就是写业务转换了,虽然转换也要写上百行代码,但是还是可控的。 然而 userModel 模式最大的问题是在于,对内存消耗非常大,一个几兆的文件解析甚至要用掉上百兆的内存。现实情况是,很多应用现在都在采用这种模式,之所以还正常在跑是因为并发不大,并发上来后,一定会OOM或者频繁的 full gc。 三、阿里出品的 EasyExcel,安利一波什么是 EasyExcel? 见名知意,就是让你操作 Excel 异常的酸爽。先来看下 EasyExcel GitHub 官方截图: ...

June 13, 2019 · 3 min · jiezi

如何通过-Freemark-优雅地生成那些花里胡哨的复杂样式-Excel-文件

欢迎关注个人微信公众号: 小哈学Java, 文末分享阿里 P8 高级架构师吐血总结的 《Java 核心知识整理&面试.pdf》资源链接!!个人网站: https://www.exception.site/essay/how-to-create-complex-style-excel-with-freemark 一、背景小哈最近这段时间开始负责一个新的产品:下载中心。啥玩意这是? 产品的目的其实就是统一管控各业务组文件下载功能(包括一些海量数据的导出,文件合并上传等),项目组不用自己再去实现各式各样的文件(PDF, Word, Excel)生成, 统一对接下载中心,由下载中心统一完成文件的生成、合并、上传、下载流程。 问题来了,这里面包括一些复杂文件的生成,如带有复杂样式的 Excel 文件,比如下面这个样子的: 这种复杂样式的 Excel, 如果说放到各个业务线去实现还是好办的,因为站在各个业务组的角度,场景变化不会太多,按照文件格式,代码写死即可。 但是站在下载中心的角度,因为需要对接各个业务中心,每个业务中心生成的样式都不一样,不可能每个业务组接进来,我都得定制的写一套生成代码吧!这显然也不合常理! 那么,有没有什么一劳永逸的办法呢?答案是肯定的! 二、实现思路要说实现方式,你的脑海里可能第一会想到传统的 Apache poi,jxl ,亦或者是阿里出品 EasyExcel 等等。 PS: 关于阿里的 EasyExcel, 小哈之前有分享过 ,没看过的小伙伴们,可以看下《7 行代码优雅地实现 Excel 文件生成&下载功能》。 对于这种复杂样式,要是用 Apache poi, jxl, 阿里 EasyExcel 去实现,不可避免的,代码肯定会非常繁琐。 有没有啥优雅(偷懒的)的方式呢? 其实我们可以通过视图引擎 Freemark、Velocity 来帮我们生成复杂样式 Excel 文件,无需关心花里胡哨的复杂样式,只关注于填充数据即可。接下来,我们以 Freemark 作为示例来讲解,如何生成这个复杂样式的 Excel 文件。 拓展阅读: 什么是 Freemark ?FreeMarker 是一款 模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。 其实,对于Java 后端来说,它更常被用来服务端动态渲染 html 页面返回给浏览器。前些年还比较火热,近些年因为前后端分离的火热,也开始慢慢淡出视野了。 ...

June 8, 2019 · 2 min · jiezi

spreadjs使用

初始化表单APIconst spreadNS = GC.Spread.Sheets;const SHEETS = new spreadNS.Workbook(this.refs['overseas']);// set sheet count// SHEETS.setSheetCount(1);const sheet = SHEETS.sheets[0];设置默认属性const defaultStyle = new GC.Spread.Sheets.Style();// 设置默认背景色// @method1 defaultStyle.backColor = "LemonChiffon";// @method2 SHEETS.options.backColor = "#ccc"; //defaultStyle.foreColor = "Red";//defaultStyle.formatter = "0.00";defaultStyle.font = "bold normal 9px normal"defaultStyle.hAlign = GC.Spread.Sheets.HorizontalAlign.center;defaultStyle.vAlign = GC.Spread.Sheets.VerticalAlign.center;//defaultStyle.borderLeft = new GC.Spread.Sheets.LineBorder("Green",GC.Spread.Sheets.LineStyle.medium);//defaultStyle.borderTop = new GC.Spread.Sheets.LineBorder("Green",GC.Spread.Sheets.LineStyle.medium);//defaultStyle.borderRight = new GC.Spread.Sheets.LineBorder("Green",GC.Spread.Sheets.LineStyle.medium);//defaultStyle.borderBottom = new GC.Spread.Sheets.LineBorder("Green",GC.Spread.Sheets.LineStyle.medium);sheet.setDefaultStyle(defaultStyle, spreadNS.SheetArea.viewport);表格的四个部分spreadNS.SheetArea.viewport// spreadNS.SheetArea include the following parts// colHeader: 1 ,// corner: 0// rowHeader: 2// viewport: 3// 改变表头的背景 Set the backcolor of second row header.sheet.getCell(1, 0, GC.Spread.Sheets.SheetArea.rowHeader).backColor("Yellow");其他配置// 表格下边的tab的颜色 sheet.options.sheetTabColor = "red";// 表格只读 sheet.options.isProtected = true// 允许cell内容移除activeSheet.options.allowCellOverflow = true;// 第一列不可见sheet.setColumnVisible(0, false)// 添加tips sheet.comments.add(4, 4, "不要修改!");// 禁止用户编辑公式 spread.options.allowUserEditFormula = false;// 不显示格子的边 sheet.options.gridline = { color:"red", showVerticalGridline: true, showHorizontalGridline: false};// 不显示表头 activeSheet.options.colHeaderVisible = false;activeSheet.options.rowHeaderVisible = false;减少重绘spread.reset() // 清空数据 spread.suspendPaint(); //suspendPaint 暂停重绘 先这样 很多操作之后 resumePaintspread.addSheet(0);spread.fromJSON(json); // json dataspread.resumePaint(); // 调用resumePaint 重新激活Spread重绘 excel 运算符引用运算符 含义(示例):(冒号) 区域运算符,产生对包括在两个引用之间的所有单元格的引用 (B5:B15),(逗号) 联合运算符,将多个引用合并为一个引用 (SUM(B5:B15,D5:D15))(空格) 交叉运算符产生对两个引用共有的单元格的引用。(B7:D7 C6:C8)设置单元格属性 sheet.getCell(2, 1).text("huahua"). // 设置文字 backColor("rgba(1,1,1,.3)") //设置背景色 公式// 随机数 sheet.setFormula(1, 1, "RandBetween(45,85)");// 求和 sheet.setFormula(1, 1, "SUM(A1,B1)"); //A1和B1之和sheet.setFormula(1, 1, "SUM(A1:H1)"); //A1到H1之和 // 条件 sheet.setFormula(4, 1, "IF(A1>10, A1*2, A1*3)");开启R1C1 引用// open r1c1 referenceSHEETS.options.referenceStyle = 1;基本操作// 添加行/列 sheet.addRows(1, 1); sheet.addColumns(1, 1);// 设置背景图片activeSheet.getCell(1, 1).backgroundImage("Image file path name");设置row和column的背景色/*** @name set the bgColor of column** @type1* sheet.getRange(-1, 1, -1, 1).backColor("lightYellow").width(330);** @name set the bgColor of row** @type1* sheet.getRange(0, -1, 1, -1).backColor("lightYellow").height(44)** @type2* const rowStyle1 = new spreadNS.Style();* rowStyle1.backColor = "#bdcde3";* sheet.setStyle(0, -1, rowStyle1, spreadNS.SheetArea.viewport);*/events// 获取点击的cell和所在的sheet SHEETS.bind(spreadNS.Events.EnterCell, function (event, data) { console.log(data.col) console.log(data.row) console.log(data) var activeSheet = data.sheet; activeSheet.startEdit(true);});// 离开cell事件 sheet.bind(GC.Spread.Sheets.Events.LeaveCell, function (event, infos) { //Reset the backcolor of cell before moving infos.sheet.getCell(infos.row, infos.col).backColor(undefined);});

May 30, 2019 · 2 min · jiezi

SpringBoot-读取文件代码模版

引言Alice上线后,学生导入模版文件下载失败。 未打包是没问题的,打完包后就发生了错误。开始逐步定位问题。 原方法File file = ResourceUtils.getFile(ResourceUtils.CLASSPATH_URL_PREFIX + "static/导入学生模板.xlsx");InputStream inputStream = new FileInputStream(file);Workbook workbook = new XSSFWorkbook(inputStream);经测试,问题出在ResourceUtils.getFile这个方法上。 ResourceUtils.CLASSPATH_URL_PREFIX + "static/导入学生模板.xlsx"字符串拼接后就是classpath:static/导入学生模板.xlsx,没打包时,该方法能正常获取到该Excel文件。 ResourceUtils.getFile是获取磁盘上的文件,而打完包之后,resources目录了下的所有资源都被打进了jar包,所以不存在相应的Excel文件,获取的时候就报错了。找不到文件。 测试将打好的jar包解压,主要的东西都在BOOT-INF里。META-INF里面有pom.xml,应该是存储项目信息的。org目录内是springframework的一些class字节码。 BOOT-INF内就是本项目的核心代码与第三方库。 classes目录下就是本项目的核心代码,我们的Excel就在这里面。 lib目录下是项目中引用的第三方jar包,里面有我们常用的slf4j,spring-boot等jar包。 所以,Spring Boot的项目一般都较大,有一部分原因是把许多第三方包都打包进去了。 解决方案@Autowired一个ResourceLoader,然后调用getResource方法,加载资源。 想想也不难理解,SpringBoot启动时读取application.yml配置,Spring的源码中就是使用ResourceLoader实现的。 只不过源码中直接用的上下文对象,一个上下文对象不只是一个IOC容器,还是一个资源加载器。(上下文其实有很多的功能,可以点开Spring源码看一看,很有意思。) ResourcePatternResolver派生自ResourceLoader接口。 代码模版,以后读取文件就这样写,啥毛病没有: Resource resource = this.resourceLoader.getResource(ResourceUtils.CLASSPATH_URL_PREFIX + "static/导入学生模板.xlsx");总结千淘万漉虽辛苦,吹尽狂沙始到金。——刘禹锡《浪淘沙词九首·其九》一路走来,一路总结。最后留下的,是小本本中记录的代码模版与最佳实践。

May 24, 2019 · 1 min · jiezi

Go-语言-Excel-类库-Excelize-200-版本发布

Excelize 是 Go 语言编写的用于操作 Office Excel 文档类库,基于 ECMA-376 Office OpenXML 标准。可以使用它来读取、写入由 Microsoft Excel™ 2007 及以上版本创建的 XLSX 文档。相比较其他的开源类库,Excelize 支持写入原本带有图片(表)、透视表和切片器等复杂样式的文档,还支持向 Excel 文档中插入图片与图表,并且在保存后不会丢失文档原有样式,可以应用于各类报表系统中。 GitHub: github.com/360EntSecGroup-Skylar/excelize 2019年4月23日, 社区正式发布了 2.0.0 版本,该版本包含了很多新功能、错误修复和性能优化。下面是有关该版本更新内容的摘要,完整的更改列表可查看 change log. Release Notes此版本中最显著的变化包括: API 更改下表列出了 v2.0.0 相比较于 v1.4.1 版本,API 的更改情况: 函数名增加 error 返回值行号计算方法变更*删除新增ToALphaString××√×TitleToNumber××√×SplitCellName×××√JoinCellName×××√ColumnNameToNumber×××√ColumnNumberToName×××√CellNameToCoordinates×××√CoordinatesToCellName×××√DuplicateRowTo×××√SetCellFloat×××√SetCellStyle√×××InsertCol√×××RemoveCol√×××RemoveRow√√××InsertRow√√××DuplicateRow√×××SetRowHeight√×××GetRowHeight√×××GetCellValue√×××GetCellFormula√×××GetCellHyperLink√×××SetCellHyperLink√×××SetCellInt√×××SetCellBool√×××SetCellStr√×××SetCellDefault√×××GetCellStyle√×××SetCellValue√×××MergeCell√×××SetSheetRow√×××SetRowVisible√√××GetRowVisible√√××SetRowOutlineLevel√√××GetRowOutlineLevel√√××GetRows√×××Columns√×××SearchSheet√×××GetPicture√×××AutoFilter√×××GetColVisible√×××SetColVisible√×××GetColOutlineLevel√×××SetColOutlineLevel√×××SetColWidth√×××GetColWidth√×××GetMergeCells√×××ProtectSheet√×××UnprotectSheet√×××UpdateLinkedValue√×××SetSheetVisible√×××adjustHelper√×××adjustMergeCells√×××adjustAutoFilter√×××prepareCell√×××setDefaultTimeStyle√×××timeToExcelTime√×××addDrawingChart√×××addDrawingVML√×××addDrawingPicture√×××getTotalRowsCols√×××checkRow√×××addDrawingShape√×××addTable√×××workSheetReader√×××copySheet√×××* 从版本 v2.0.0 开始,所有行操作方法都使用从 1 开始的 Excel 行编号,早期版本中某些方法中的基于 0 的行编号将不再使用,参考相关 issue #349。 新增功能新增 DuplicateRowTo() 方法, 支持根据给定的工作表名称(大小写敏感)和行号,在指定行后复制该行工作表页面布局设置函数 SetPageLayout() 新增对页面布局方向设置的支持,解决了相关 issue #318工作表页面布局设置函数 SetPageLayout() 新增对页面纸张大小设置的支持问题修复修复部分情况下,在样式格式中未指定单元格颜色填充时,创建了空白填充的问题修复当工作表数据验证公式超过 225 个字符时,文件打开失败的问题,解决了相关 issue #339修复部分情况下,删除带有公式的单元格会导致文件损坏的问题,解决了相关 issue #346修复通过获取批注函数 GetComment(),从包含多个工作表的工作簿获取批注时,返回了错误的工作表名称的问题,解决了相关 issue #345修复获取工作表全部单元格函数 GetRows() 返回多余的列的问题修复部分情况下删除包含公式的工作表引起文档损坏的问题性能提升单元格赋值系列函数、添加批注、图片、图表、超链接和形状函数的性能,均获得了大幅提升新增重复图片检查,将用添加引用代替添加重复图片,解决了相关 issue #359 ...

April 24, 2019 · 1 min · jiezi

openpyxl 基础操作

直接复制代码到编辑器,边看边运行,理解起来估计还快些~from openpyxl import load_workbookfrom openpyxl import Workbook# =============== 第一部分,创建并写入数据 =====================# 创建一个test.xlsx表,并写入数据# wb = Workbook()# ws = wb.active# for row in range(1,4):# ws.append([row10+1,row10+2,row*10+3])# wb.save(‘data/test.xlsx’)# exit()# 导入一个已存在的test.xlsxload_wb = load_workbook(‘data/test.xlsx’)# 打开活动的工作薄的活动工作簿,或者指定的工作簿load_ws = load_wb.active# ============== 第二部分,插入、删除行和列 ========================# load_ws = load_wb.get_sheet_by_name(“Sheet”)# 1-①在第二行前插入2行# load_ws.insert_rows(2,1)# 1-②从第二行开始删除1行# load_ws.delete_rows(2,1)# 2-①在第二列前插入2列# load_ws.insert_cols(2,2)# 2-②从第二列开始删除1列# load_ws.delete_cols(2,1)# 获取总行数(存在数据)# load_wb.save(‘data/test.xlsx’)# rows = load_ws.max_row# cols = load_ws.max_column# print(‘该表格总共有:’+str(rows)+’ 行’)# print(‘该表格总共有:’+str(cols)+’ 列’)# exit()# ============== 第三部分,获取单元格的值 ========================# 获第三行第一列的值,两种方法都行# 方法一,根据单元格名称获取# v = load_ws[‘A3’].value# 方法二,根据横纵坐标值来获取# v = load_ws.cell(3,1).value# print(v)# 获取全部的单元格# rows = load_ws.rows# for row in rows:# for cell in row:# if(cell.value==21):# print(dir(cell))# #可用属性 col_idx、column、row、value# print(cell.col_idx)# print(cell.column)# print(cell.row)# ============== 第三部分,修改指定单元格的值 ========================# load_ws[‘A2’] = ‘xx’# load_wb.save(‘data/test.xlsx’)# exit()# ============== 第四部分,合并单元格 ========================# load_ws.merge_cells(‘A2:B2’)# load_wb.save(‘data/test.xlsx’)# exit()# ============== 第五部分,设置样式(文字居左) ========================# from openpyxl.styles import Alignment# # 水平居右,垂直居中,自动换行# load_ws[‘A2’].alignment = Alignment(horizontal=‘right’,vertical=‘center’,wrap_text=True)# # 自动换行# load_ws[‘G1’].alignment = Alignment(wrap_text=True)## from openpyxl.styles import Font# # 设置字体为“宋体”,大小为11,bold为加粗,italic为斜体,strike为删除线,颜色为黑色# font = Font(u’宋体’,size = 11,bold=True,italic=True,strike=True,color=‘000000’)# load_ws[‘A1’].font = font# from openpyxl.styles import PatternFill# # 设置背景色为 #1874CD# fill = PatternFill(“solid”, fgColor=“1874CD”)# load_ws[‘C3’].fill = fill# 第2行行高load_ws.row_dimensions[2].height = 40# C列列宽load_ws.column_dimensions[‘C’].width = 30load_wb.save(‘data/test.xlsx’)exit()# ============== 第六部分,其它 ========================# # 打印设置# load_ws.print_options.horizontalCentered = True# load_ws.print_options.verticalCentered = True# load_ws.print_area = ‘A1:I5’# load_wb.save(‘data/test.xlsx’)from openpyxl.utils import get_column_letter, column_index_from_string# 根据列的数字返回字母print(get_column_letter(2)) # B# 根据字母返回列的数字print(column_index_from_string(‘D’)) # 4 ...

March 14, 2019 · 1 min · jiezi

纯前端表格控件 SpreadJS 内测邀请

纯前端类 Excel 表格 SpreadJS 自发布以来,受到了各行业开发伙伴们的认可,无论国内互联网巨头、上市公司、行业龙头以及跨国集团都将 SpreadJS 作为核心组件应用于多个场景,如报表展示、数据分析、数据填报、办公协同、报告生成和在线文档等。值此 SpreadJS V12 SP1 新版本发布前夕,葡萄城 SpreadJS 产品组特举办本次新版本内测活动,诚邀您的参与。点击下载 SpreadJS V12 SP1内测版同时,我们也希望得到您关于产品宝贵的意见或建议,无论是产品 Bug、新功能,甚至是主题配色等,都将促使我们不断优化并完善 SpreadJS 产品,为您提供更专业的服务。请您点击链接或扫描图中二维码,提交内测反馈。再次感谢您的参与和支持,让我们共同笃定前行,赋能更多开发者!关于 SpreadJS 前端表格控件SpreadJS 纯前端表格控件是基于 HTML5 的 JavaScript 电子表格和网格功能控件,适用于 .NET、Java 和移动端等各平台在线编辑类 Excel 功能的表格程序开发。全中文操作界面,零学习成本!便于您在系统开发过程中,更好的显示和管理类似 Excel 的数据,更方便的进行公式引擎、排序、过滤、输入控件、数据可视化、Excel 导入/导出等操作。

March 12, 2019 · 1 min · jiezi

复杂 Excel 表格导入导出的最简方法

把 Excel 文件导入关系数据库是数据分析业务中经常要做的事情,但许多 Excel 文件的格式并不规整,需要事先将其中的数据结构化后再用 SQL 语句写入数据库。JAVA程序猿经常选择使用POI或者HSSFWorkbook等第三方类库来实现,通常都要硬编码,如果碰到格式复杂的表格,解析工作量还会成倍增加,Java没有表格对象,总要利用集合加实体类去实现,导致代码冗长、不通用。集算器的 SPL 是专业处理结构化数据的语言,它能够轻松读取 excel 数据,然后结构化成“序表”后导入数据库。使用 SPL 语言后,以往需要编写数千行代码才能完成的 Excel 数据结构化入库工作,现在只需要不到 10 行代码就可以胜任,简单情况下甚至只需要 2、3 行代码。而关于导出,有时我们需要用程序来自动生成 Excel 文件,但 Excel 本身带的 VBA 并不好用,集算器作为数据处理工具实现这个需求就会方便很多。本文中用到的函数请参看集算器文档《函数参考》。下面我们就来了解一下集算器是如何对表格数据进行导入或导出的:导入1、普通行式表格样式:集算器脚本:脚本说明:A1:打开“学生成绩表.xlsx”文件并导入成序表,选项@t表示文件第一行是列标题;A2:连接demo数据库;A3:将A1中的序表存入到demo数据库的xscj表中,由于表中的列名和序表中的字段名一样,所以只需指定数据表名即可。导入效果:2、多行表头行式表格样式:集算器脚本:脚本说明:A1:打开文件并导入数据成序表,参数“1,5”表示读第一个 sheet,从第 5 行开始读,一直读到文件结尾;A2:将 A1 中读到的序表列名依次改为“序号、项目编码、项目名称、计量单位、数量、单价、合价”,即要存入的数据表的列名。导入效果:3、自由格式表格样式:集算器脚本:脚本说明:A1:创建列名为“雇员 ID, 姓名, 性别, 职位, 生日, 电话, 地址, 邮编”的空序表A2:打开 Excel 数据文件A3:定义雇员信息所在单元格列号序列B3:定义雇员信息所在单元格行号序列A4:用 for 循环读取每个雇员信息B4:A3.(~/B3(#))先算出当前雇员单元格编号序列, 再读出这些单元格值组成雇员信息序列。第一次循环时为 [C1,C2,F2,C3,C4,D5,C7,C8],第二次循环时为[C10,C11,F11,C12,C13,D14,C16,C17]……每次行号加 9。$[A2.xlscell(] 与 “A2.xlscell(” 相同,都是表示一个字符串,它的好处是在 IDE 中编写程序时,如果 A2 单元格的编号发生了变化,$[A2.xlscell(]中的 A2 会自动变化,比如在 A2 前插入了一行,这个表达式就会变成 $[A3.xlscell(],而用引号的话,就不会自动变了。B5:判断雇员 ID 值是否为空,为空则退出循环,结束运行B6:将一条雇员信息存入 A1 序表尾B7:让雇员信息的行号序列都加上 9,读取下一条雇员信息导入效果:4、交叉表表格样式:集算器脚本:脚本说明:A1:打开文件并导入数据成序表,参数“1,2”表示读第一个 sheet,从第 2 行开始读,一直读到文件结尾。选项 @t 表示开始行是列标题。A2:由于第二行第一个单元格是图片,读的数据为 null,第一列没有列标题,所以将第一列列名改为运货商。A3:以运货商为分组,对序表数据进行行列转换,选项 @r 表示将列数据转换为行数据,转换后新的列名分别为“货主地区”、“订单数量”。导入效果:5、主子表表格样式:集算器脚本:脚本说明:A1:创建列名为“身份证号, 姓名, 性别, 出生日期, 民族, 手机号, 部门, 家庭地址, 婚姻状况, 入职时间”的空序表,用于保存主表员工信息;A2:创建列名为“身份证号, 姓名, 关系, 工作单位, 联系电话”的空序表,用于保存子表员工家庭成员信息;A3:定义主表员工信息所在单元格序列;A4:打开 Excel 数据文件;A5:循环读取 Excel 文件各 sheet 数据;B6:读取员工信息序列;C6:将 B6 读取的员工信息保存到序表 A1;B7:从第 6 行开始读取员工家庭成员信息,只读指定的“家庭成员, 姓名, 关系, 工作单位, 联系电话”5 列;B8:将 B7 序表的家庭成员列改名为身份证号;C8:为 B8 序表的身份证号列赋值为员工信息中的身份证号;B9:将 B8 中的员工家庭成员信息保存到序表 A2。导入效果:序表A1如下图:序表A2如下图:上面这些情况基本罗列了常见的 Excel 数据格式,如果遇到更复杂的文件,也可以灵活使用例子中的技巧予以应对。导出基础篇1、单纯导出数据(1)导出新文件集算器脚本:脚本说明:A1:读入文本格式的某企业订单表,用来模拟可能通过计算得到的数据;A2:将 A1 的数据导出到 orders.xlsx 文件中 (如果文件不存在,程序运行时会自动创建)。例子中导出函数 xlsexport 参数中没有指定 x 和 F,因此将导出 A1 中的所有字段,同时保持字段名不变。由于没有指定参数 s,所以会导出到 sheet1 中。而函数使用了选项 @t,因此会将字段名导出到第一行。导出效果:(2)追加数据集算器脚本:脚本说明:A1:读入文本格式的某日订单数据表;A2:导出时不要加函数选项 @t,因为文件中已有标题,只需导出数据。由于文件已存在,因此会自动追加在原来数据的后面。(3)导出到不同 sheet集算器脚本:脚本说明:A1:读入文本格式的某企业订单表;A2:对序表 A1 进行过滤,只选出公司名称为山泰企业的数据记录;A3:将新序表 A2 导出到 orders.xlsx 中,只导出订单 ID、公司名称、订购日期、订单金额四个字段,并将订购日期改名为日期,订单金额改名为金额,数据导出到一个名为山泰企业的新 sheet 中。导出效果:2、导出大量数据集算器脚本:脚本说明:A1:读入文本格式某数据量较大的表;A2:将游标所指的大数据导出到 big.xlsx 文件中。在用游标导出时,要添加 @s 这个函数选项,这样在导出时就会以流式导出,产生的 excel 结果文件也不会占用在内存中。导出效果:注:本例中导出了 130727 条数据记录。事实上我们可以导出上亿条记录也不在话下,不过 excel 文件的一个 sheet 最多只能存放 1048576 行数据,所以当导出数据超过百万行时,会在 excel 中新增一个 sheet 来保存。3、指定显示属性除了直接导出数据,有时我们还希望生成的 excel 文件能够显示得比较美观,比如可以指定字体、颜色、背景色、对齐方式、显示格式等。这时,只要我们预先建好这个 excel 文件(模板),定义好我们需要的这些显示属性,然后再用集算器向这个文件中导出数据,定义好的显示属性就会随之呈现。表格样式:在 orders.xlsx 文件 sheet1 的第一行写上表格名称,在第二行写上字段列名,并对表名和各列定义一些样式属性,第 1、3、4 列中间对齐,第 2 列左对齐,第 5 列右对齐,第 4 列显示格式为“yyyy 年 mm 月 dd 日”,第 5 列显示格式为“#,###.00”。集算器脚本:导出样式:注:导出时会使用原文件中定义的各种样式属性;大数据流式导出时不支持。4、固定行列填数据集算器里还提供了读写 excel 文件中指定的某单元格或某区块单元格的方法,这个功能在用 excel 作数据填报时非常有用。比如某基金公司总公司向分公司下发了一张 excel 表格,要求分公司填入它的相关数据后回传给总公司,下发的 excel 文件如下:集算器脚本:脚本说明:前 5 行是依次要填的数据;样表中前 6 个要填的单元格都是独立的,所以只能每次填一个格,第 6 行是可以连续填写的单元格,此时就把要填的数据拼成以 \t 分隔的字符串,可以同行中按顺序填入。数据全部填写完以后,再把 C6 打开的 excel 对象写回到 hb.xlsx 文件中。导出样式:高级篇1、动态条件的显示属性导出需求:数据行的背景色以两种颜色隔行交替显现,订单金额大于 2000 的用红色显示,低于 500 的用绿色显示。报表设计:新建报表数据集 ds1,这个数据集只用于从集算器接收导出的序表数据,所以只需指定数据集名称。报表的第一行是表名称,第二行是要导出的列名称,第三行是数据记录行,数据记录的具体写法可以参阅润乾报表的相关教程。选中第三行的所有单元格,在背景色表达式中填入:if(row()%2==0,-853778,-1),用来指定交替显示的两种背景色。选择第三行最后一个单元格,指定显示格式为 #.00,在前景色表达式中填入:if(value()>2000,-65536,if(value()<500,-16711936,-16777216)),指定根据不同金额显示不同的字体颜色。集算器脚本:脚本说明:A1:读入要导出的序表数据;A2:进行报表环境的配置,主要是配置报表主目录以及授权文件;A3:打开我们刚才设计的报表模板;A4:将 A1 中的序表作为数据集 ds1 对传递给报表对象 A3 进行计算;A5:将计算后的报表对象 A3 导出成 excel 文件。导出效果:2、分组带明细及统计报表设计:建立数据集 ds1,在 A3 格按货主地区进行分组,B3 格按公司名称进行分组,C3、D3、E3 显示订单明细。E4 格统计各公司的订单金额总和,E5 格统计各地区的订单金额总和。集算器脚本:脚本说明:A1:读入要导出的序表数据;A2:进行报表环境的配置,主要是配置报表主目录以及授权文件;A3:打开我们刚才设计的报表模板;A4:将 A1 中的序表作为数据集 ds1 对传递给报表对象 A3 进行计算;A5:将计算后的报表对象 A3 导出成 excel 文件。导出样式:3、交叉统计表报表设计:建立数据集 ds1,B2 格按订购日期的年份分组,A3 格按货主地区分组,B3 格统计各分组的订单金额总和。集算器脚本:脚本说明:A1:读入要导出的序表数据;A2:进行报表环境的配置,主要是配置报表主目录以及授权文件;A3:打开我们刚才设计的报表模板;A4:将 A1 中的序表作为数据集 ds1 对传递给报表对象 A3 进行计算;A5:将计算后的报表对象 A3 导出成 excel 文件。导出样式:总结集算器提供了非常灵活的在 excel 文件中定位和读取数据的功能,既可以成片读取网格数据,也可以精确定位单元格进行读取。再结合特有的“序表”对象,以往需要编写数千行代码才能完成的 Excel 数据结构化入库工作,现在只需要不到 10 行,甚至两三行代码就可以胜任。而关于导出,在润乾报表丰富的设计能力基础上,通过集算器将计算得到的数据传递给润乾报表,然后再导出为 Excel,我们就能够将数据以更加丰富直观的方式提供给业务人员阅读使用,而处理过程也会因为自动化而变得更加快捷。 ...

March 11, 2019 · 2 min · jiezi

POI如何高效导出百万级Excel数据?

阅读原文:POI如何高效导出百万级Excel数据?在一个具有统计功能的系统中,导出excel功能几乎是一定的,如何导出excel?导出的数据有多少?如何高效的导出?Excel简介什么是excel就不用介绍了,这里主要说明不同版本下每个sheet下的行列限制。由上面可知 Excel 2003及以下是无法实现单sheet百万级的数据。Apache POI简介Apache POI 是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java程式对Microsoft Office(Excel、WORD、PowerPoint、Visio等)格式档案读和写的功能。POI为“Poor Obfuscation Implementation”的首字母缩写,意为“可怜的模糊实现”。常用类HSSF - 提供读写Microsoft Excel XLS格式档案的功能。XSSF - 提供读写Microsoft Excel OOXML XLSX格式档案的功能。SXSSF - 一种基于XSSF的低内存占用的API(3.8版本开始出现)。HWPF - 提供读写Microsoft Word DOC97格式档案的功能。XWPF - 提供读写Microsoft Word DOC2003格式档案的功能。HSLF - 提供读写Microsoft PowerPoint格式档案的功能。HDGF - 提供读Microsoft Visio格式档案的功能。HPBF - 提供读Microsoft Publisher格式档案的功能。HSMF - 提供读Microsoft Outlook格式档案的功能。我们这里是导出Excel,所以使用的是前三个。导出策略方案使用XSSF和SXSSF分别导入1w,10w,100w数据使用SXSSF,SXSSF以10w分页,SXSSF多线程以10w分页导入100w数据性能对比时间不包含网络耗时总结方案一:数据在万条时XSSF和SXSSF相差不大数据上十万后SXSSF性能开始突出数据到达百万时,XSSF已不适合使用方案二:不进行分表时,SXSSF最多可存储1048576行百万级数据分表存储时,使用多线程导出几乎是不使用多线程导出的一半时间最终我得出一个导出百万级数据的最高效方案:多线程分表导出实战controller层:@RestController @RequestMapping(“export”)public class ReportController {public static final String[] TITLE = new String[]{“第1列”, “第2列”, “第3列”, “第4列”, “第5列”};public static final String SHEET_NAME = “page1”;@RequestMapping(value = “/sxssf/page/thread”)@ResponseBodypublic void exportSXSSFWorkbookByPageThread(HttpServletResponse response, Integer num) throws Exception { //excel文件名 String fileName = System.currentTimeMillis() + “.xlsx”; //sheet名 if (Objects.isNull(num)) { num = 65536; } String[][] content = buildContent(num); long start = System.currentTimeMillis(); SXSSFWorkbook wb = ExcelUtil.getSXSSFWorkbookByPageThread(TITLE, content, null); long millis = System.currentTimeMillis() - start; long second = millis / 1000; System.out.println(“SXSSF Page Thread 导出” + num + “条数据,花费:” + second + “s/ " + millis + “ms”); writeAndClose(response, fileName, wb); wb.dispose();}/** * 构建内容 * @param num * @return */private String[][] buildContent(Integer num) { String[][] content = new String[num][4]; for (int i = 0; i < content.length; i++) { content[i][0] = “1”; content[i][5] = “2”; content[i][6] = “3”; content[i][7] = “4”; content[i][8] = “5”; } return content;}private void writeAndClose(HttpServletResponse response, String fileName, Workbook wb) { try { this.setResponseHeader(response, fileName); OutputStream os = response.getOutputStream(); wb.write(os); os.flush(); os.close(); } catch (Exception e) { e.printStackTrace(); }}public void setResponseHeader(HttpServletResponse response, String fileName) { try { try { fileName = new String(fileName.getBytes(), “UTF-8”); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } response.setContentType(“application/octet-stream;charset=ISO8859-1”); response.setHeader(“Content-Disposition”, “attachment;filename=” + fileName); response.addHeader(“Pargam”, “no-cache”); response.addHeader(“Cache-Control”, “no-cache”); } catch (Exception ex) { ex.printStackTrace(); }}}工具类:public class ExcelUtil { public static final int PER_SHEET_LIMIT = 500000; public static SXSSFWorkbook getSXSSFWorkbookByPageThread(String[] title, String[][] values) { SXSSFWorkbook wb = new SXSSFWorkbook(); int pageNum = values.length / PER_SHEET_LIMIT; int lastCount = values.length % PER_SHEET_LIMIT; if (values.length > PER_SHEET_LIMIT) { CellStyle style = wb.createCellStyle(); int sheet = lastCount == 0 ? pageNum : pageNum + 1; CountDownLatch downLatch = new CountDownLatch(sheet); Executor executor = Executors.newFixedThreadPool(sheet); for (int c = 0; c <= pageNum; c++) { int rowNum = PER_SHEET_LIMIT; if (c == pageNum) { if (lastCount == 0) { continue; } rowNum = lastCount; } Sheet sheet = wb.createSheet(“page” + c); executor.execute(new PageTask(downLatch, sheet, title, style, rowNum, values)); } try { downLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } } return wb;}}分表任务类:public class PageTask implements Runnable {private CountDownLatch countDownLatch;private Sheet sheet;private String[] title;private CellStyle style;private int b;private String[][] values;public PageTask(CountDownLatch countDownLatch, Sheet sheet, String[] title, CellStyle style, int b, String[][] values) { this.countDownLatch = countDownLatch; this.sheet = sheet; this.title = title; this.style = style; this.b = b; this.values = values;}@Overridepublic void run() { try { Row row = sheet.createRow(0); Cell cell = null; for (int i = 0; i < title.length; i++) { cell = row.createCell(i); cell.setCellValue(title[i]); cell.setCellStyle(style); } for (int i = 0; i < b; i++) { row = sheet.createRow(i + 1); for (int j = 0; j < values[i].length; j++) { row.createCell(j).setCellValue(values[i][j]); } } } catch (Exception e) { e.printStackTrace(); } finally { if (countDownLatch != null) { countDownLatch.countDown(); } }}} ...

March 8, 2019 · 3 min · jiezi

规则引擎RulerZ用法及实现原理解读

规则引擎RulerZ用法及实现原理解读废话不多说,rulerz的官方地址是:https://github.com/K-Phoen/ru…注意,本例中只拿普通数组做例子进行分析1. 简介RulerZ是一个用php实现的composer依赖包,目的是实现一个数据过滤规则引擎。RulerZ不仅支持数组过滤,也支持一些市面上常见的ORM,如Eloquent、Doctrine等,也支持Solr搜索引擎。这是一个缺少中文官方文档的开源包,当然由于star数比较少,可能作者也觉得没必要。2.安装在你的项目composer.json所在目录下运行:composer require ‘kphoen/rulerz'3.使用 - 过滤现有数组如下:$players = [ [‘pseudo’ => ‘Joe’, ‘fullname’ => ‘Joe la frite’, ‘gender’ => ‘M’, ‘points’ => 2500], [‘pseudo’ => ‘Moe’, ‘fullname’ => ‘Moe, from the bar!’, ‘gender’ => ‘M’, ‘points’ => 1230], [‘pseudo’ => ‘Alice’, ‘fullname’ => ‘Alice, from… you know.’, ‘gender’ => ‘F’, ‘points’ => 9001],];初始化引擎:use RulerZ\Compiler\Compiler;use RulerZ\Target;use RulerZ\RulerZ;// compiler$compiler = Compiler::create();// RulerZ engine$rulerz = new RulerZ( $compiler, [ new Target\Native\Native([ // 请注意,这里是添加目标编译器,处理数组类型的数据源时对应的是Native ’length’ => ‘strlen’ ]), ]);创建一条规则:$rule = “gender = :gender and points > :min_points’将参数和规则交给引擎分析。$parameters = [ ‘min_points’ => 30, ‘gender’ => ‘F’,];$result = iterator_to_array( $rulerz->filter($players, $rule, $parameters) // the parameters can be omitted if empty );// result 是一个过滤后的数组array:1 [▼ 0 => array:4 [▼ “pseudo” => “Alice” “fullname” => “Alice, from… you know.” “gender” => “F” “points” => 9001 ]]4.使用 - 判断是否满足规则$rulerz->satisfies($player, $rule, $parameters);// 返回布尔值,true表示满足5.底层代码解读下面,让我们看看从创建编译器开始,到最后出结果的过程中发生了什么。1.Compiler::create();这一步是实例化一个FileEvaluator类,这个类默认会将本地的系统临时目录当做下一步临时类文件读写所在目录,文件类里包含一个has()方法和一个write()方法。文件类如下:<?phpdeclare(strict_types=1);namespace RulerZ\Compiler;class NativeFilesystem implements Filesystem{ public function has(string $filePath): bool { return file_exists($filePath); } public function write(string $filePath, string $content): void { file_put_contents($filePath, $content, LOCK_EX); }}2.初始化RulerZ引擎,new RulerZ()先看一下RulerZ的构建方法: public function construct(Compiler $compiler, array $compilationTargets = []) { $this->compiler = $compiler; foreach ($compilationTargets as $targetCompiler) { $this->registerCompilationTarget($targetCompiler); } }这里的第一个参数,就是刚刚的编译器类,第二个是目标编译器类(实际处理数据源的),因为我们选择的是数组,所以这里的目标编译器是Native,引擎会将这个目标编译类放到自己的属性$compilationTargets。 public function registerCompilationTarget(CompilationTarget $compilationTarget): void { $this->compilationTargets[] = $compilationTarget; }3.运用filter或satisfies方法这一点便是核心了。以filter为例: public function filter($target, string $rule, array $parameters = [], array $executionContext = []) { $targetCompiler = $this->findTargetCompiler($target, CompilationTarget::MODE_FILTER); $compilationContext = $targetCompiler->createCompilationContext($target); $executor = $this->compiler->compile($rule, $targetCompiler, $compilationContext); return $executor->filter($target, $parameters, $targetCompiler->getOperators()->getOperators(), new ExecutionContext($executionContext)); }第一步会检查目标编译器是否支持筛选模式。第二步创建编译上下文,这个一般统一是Context类实例 public function createCompilationContext($target): Context { return new Context(); }第三步,执行compiler的compile()方法 public function compile(string $rule, CompilationTarget $target, Context $context): Executor { $context[‘rule_identifier’] = $this->getRuleIdentifier($target, $context, $rule); $context[’executor_classname’] = ‘Executor’.$context[‘rule_identifier’]; $context[’executor_fqcn’] = ‘\RulerZ\Compiled\Executor\Executor’.$context[‘rule_identifier’]; if (!class_exists($context[’executor_fqcn’], false)) { $compiler = function () use ($rule, $target, $context) { return $this->compileToSource($rule, $target, $context); }; $this->evaluator->evaluate($context[‘rule_identifier’], $compiler); } return new $context’executor_fqcn’; } protected function getRuleIdentifier(CompilationTarget $compilationTarget, Context $context, string $rule): string { return hash(‘crc32b’, get_class($compilationTarget).$rule.$compilationTarget->getRuleIdentifierHint($rule, $context)); } protected function compileToSource(string $rule, CompilationTarget $compilationTarget, Context $context): string { $ast = $this->parser->parse($rule); $executorModel = $compilationTarget->compile($ast, $context); $flattenedTraits = implode(PHP_EOL, array_map(function ($trait) { return “\t”.‘use \’.ltrim($trait, ‘\’).’;’; }, $executorModel->getTraits())); $extraCode = ‘’; foreach ($executorModel->getCompiledData() as $key => $value) { $extraCode .= sprintf(‘private $%s = %s;’.PHP_EOL, $key, var_export($value, true)); } $commentedRule = str_replace(PHP_EOL, PHP_EOL.’ // ‘, $rule); return <<<EXECUTORnamespace RulerZ\Compiled\Executor;use RulerZ\Executor\Executor;class {$context[’executor_classname’]} implements Executor{ $flattenedTraits $extraCode // $commentedRule protected function execute($target, array $operators, array $parameters) { return {$executorModel->getCompiledRule()}; }}EXECUTOR; }这段代码会依照crc13算法生成一个哈希串和Executor拼接作为执行器临时类的名称,并将执行器相关代码写进上文提到的临时目录中去。生成的代码如下:// /private/var/folders/w_/sh4r42wn4_b650l3pc__fh7h0000gp/T/rulerz_executor_ff2800e8<?phpnamespace RulerZ\Compiled\Executor;use RulerZ\Executor\Executor;class Executor_ff2800e8 implements Executor{ use \RulerZ\Executor\ArrayTarget\FilterTrait; use \RulerZ\Executor\ArrayTarget\SatisfiesTrait; use \RulerZ\Executor\ArrayTarget\ArgumentUnwrappingTrait; // gender = :gender and points > :min_points and points > :min_points protected function execute($target, array $operators, array $parameters) { return ($this->unwrapArgument($target[“gender”]) == $parameters[“gender”] && ($this->unwrapArgument($target[“points”]) > $parameters[“min_points”] && $this->unwrapArgument($target[“points”]) > $parameters[“min_points”])); }}这个临时类文件就是最后要执行过滤动作的类。FilterTrait中的filter方法是首先被执行的,里面会根据execute返回的布尔值来判断,是否通过迭代器返回符合条件的行。execute方法就是根据具体的参数和操作符挨个判断每行中对应的cell是否符合判断来返回true/false。 public function filter($target, array $parameters, array $operators, ExecutionContext $context) { return IteratorTools::fromGenerator(function () use ($target, $parameters, $operators) { foreach ($target as $row) { $targetRow = is_array($row) ? $row : new ObjectContext($row); if ($this->execute($targetRow, $operators, $parameters)) { yield $row; } } }); }satisfies和filter基本逻辑类似,只是最后satisfies是执行单条判断。有一个问题,我们的编译器是如何知道我们设立的操作规则$rule的具体含义的,如何parse的?这就涉及另一个问题了,抽象语法树(AST)。Go further - 抽象语法树我们都知道php zend引擎在解读代码的过程中有一个过程是语法和词法分析,这个过程叫做parser,中间会将代码转化为抽象语法树,这是引擎能够读懂代码的关键步骤。同样,我们在写一条规则字符串的时候,代码如何能够明白我们写的是什么呢?那就是抽象语法树。以上面的规则为例:gender = :gender and points > :min_points这里, =、and、>都是操作符,但是机器并不知道他们是操作符,也不知道其他字段是什么含义。于是rulerz使用自己的语法模板。首先是默认定义了几个操作符。<?phpdeclare(strict_types=1);namespace RulerZ\Target\Native;use RulerZ\Target\Operators\Definitions;class NativeOperators{ public static function create(Definitions $customOperators): Definitions { $defaultInlineOperators = [ ‘and’ => function ($a, $b) { return sprintf(’(%s && %s)’, $a, $b); }, ‘or’ => function ($a, $b) { return sprintf(’(%s || %s)’, $a, $b); }, ’not’ => function ($a) { return sprintf(’!(%s)’, $a); }, ‘=’ => function ($a, $b) { return sprintf(’%s == %s’, $a, $b); }, ‘is’ => function ($a, $b) { return sprintf(’%s === %s’, $a, $b); }, ‘!=’ => function ($a, $b) { return sprintf(’%s != %s’, $a, $b); }, ‘>’ => function ($a, $b) { return sprintf(’%s > %s’, $a, $b); }, ‘>=’ => function ($a, $b) { return sprintf(’%s >= %s’, $a, $b); }, ‘<’ => function ($a, $b) { return sprintf(’%s < %s’, $a, $b); }, ‘<=’ => function ($a, $b) { return sprintf(’%s <= %s’, $a, $b); }, ‘in’ => function ($a, $b) { return sprintf(‘in_array(%s, %s)’, $a, $b); }, ]; $defaultOperators = [ ‘sum’ => function () { return array_sum(func_get_args()); }, ]; $definitions = new Definitions($defaultOperators, $defaultInlineOperators); return $definitions->mergeWith($customOperators); }}在RulerZParserParser中,有如下方法:public function parse($rule){ if ($this->parser === null) { $this->parser = Compiler\Llk::load( new File\Read(DIR.’/../Grammar.pp’) ); } $this->nextParameterIndex = 0; return $this->visit($this->parser->parse($rule));}这里要解读一个核心语法文件://// Hoa////// @license//// New BSD License//// Copyright © 2007-2015, Ivan Enderlin. All rights reserved.//// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are met:// * Redistributions of source code must retain the above copyright// notice, this list of conditions and the following disclaimer.// * Redistributions in binary form must reproduce the above copyright// notice, this list of conditions and the following disclaimer in the// documentation and/or other materials provided with the distribution.// * Neither the name of the Hoa nor the names of its contributors may be// used to endorse or promote products derived from this software without// specific prior written permission.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE// POSSIBILITY OF SUCH DAMAGE.//// Inspired from \Hoa\Ruler\Grammar.//// @author Stéphane Py <stephane.py@hoa-project.net>// @author Ivan Enderlin <ivan.enderlin@hoa-project.net>// @author Kévin Gomez <contact@kevingomez.fr>// @copyright Copyright © 2007-2015 Stéphane Py, Ivan Enderlin, Kévin Gomez.// @license New BSD License%skip space \s// Scalars.%token true (?i)true%token false (?i)false%token null (?i)null// Logical operators%token not (?i)not\b%token and (?i)and\b%token or (?i)or\b%token xor (?i)xor\b// Value%token string ("|’)(.?)(?<!\)\1%token float -?\d+.\d+%token integer -?\d+%token parenthesis_ (%token parenthesis )%token bracket [%token bracket ]%token comma ,%token dot .%token positional_parameter ?%token named_parameter :[a-z-A-Z0-9]+%token identifier [^\s()[],.]+#expression: logical_operation()logical_operation: operation() ( ( ::and:: #and | ::or:: #or | ::xor:: #xor ) logical_operation() )?operation: operand() ( <identifier> logical_operation() #operation )?operand: ::parenthesis_:: logical_operation() ::parenthesis:: | value()parameter: <positional_parameter> | <named_parameter>value: ::not:: logical_operation() #not | <true> | <false> | <null> | <float> | <integer> | <string> | parameter() | variable() | array_declaration() | function_call()variable: <identifier> ( object_access() #variable_access )*object_access: ::dot:: <identifier> #attribute_access#array_declaration: ::bracket:: value() ( ::comma:: value() ) ::bracket::#function_call: <identifier> ::parenthesis:: ( logical_operation() ( ::comma:: logical_operation() )* )? ::parenthesis::上面Llk::load方法会加载这个基础语法内容并解析出片段tokens,tokens解析的逻辑就是正则匹配出我们需要的一些操作符和基础标识符,并将对应的正则表达式提取出来:array:1 [▼ “default” => array:20 [▼ “skip” => “\s” “true” => “(?i)true” “false” => “(?i)false” “null” => “(?i)null” “not” => “(?i)not\b” “and” => “(?i)and\b” “or” => “(?i)or\b” “xor” => “(?i)xor\b” “string” => “("|’)(.*?)(?<!\)\1” “float” => “-?\d+.\d+” “integer” => “-?\d+” “parenthesis” => “(” “parenthesis” => “)” “bracket” => “[” “bracket” => “]” “comma” => “,” “dot” => “.” “positional_parameter” => “?” “named_parameter” => “:[a-z-A-Z0-9]+” “identifier” => “[^\s()[],.]+” ]]这一步也会生成一个rawRulesarray:10 [▼ “#expression” => " logical_operation()” “logical_operation” => " operation() ( ( ::and:: #and | ::or:: #or | ::xor:: #xor ) logical_operation() )?" “operation” => " operand() ( <identifier> logical_operation() #operation )?" “operand” => " ::parenthesis_:: logical_operation() ::parenthesis:: | value()" “parameter” => " <positional_parameter> | <named_parameter>" “value” => " ::not:: logical_operation() #not | <true> | <false> | <null> | <float> | <integer> | <string> | parameter() | variable() | array_declaration() | function_call( ▶" “variable” => " <identifier> ( object_access() #variable_access )*" “object_access” => " ::dot:: <identifier> #attribute_access" “#array_declaration” => " ::bracket:: value() ( ::comma:: value() )* ::bracket::" “#function_call” => " <identifier> ::parenthesis:: ( logical_operation() ( ::comma:: logical_operation() )* )? ::_parenthesis::"]这个rawRules会通过analyzer类的analyzeRules方法解析替换里面的::表示的空位,根据$_ppLexemes属性的值,Compiler\Llk\Lexer()词法解析器会将rawRules数组每一个元素解析放入双向链表栈(SplStack)中,然后再通过对该栈插入和删除操作,形成一个包含所有操作符和token实例的数组$rules。array:54 [▼ 0 => Concatenation {#64 ▶} “expression” => Concatenation {#65 ▼ #_name: “expression” #_children: array:1 [▼ 0 => 0 ] #_nodeId: “#expression” #_nodeOptions: [] #_defaultId: “#expression” #_defaultOptions: [] #_pp: " logical_operation()" #_transitional: false } 2 => Token {#62 ▶} 3 => Concatenation {#63 ▼ #_name: 3 #_children: array:1 [▼ 0 => 2 ] #_nodeId: “#and” #_nodeOptions: [] #_defaultId: null #_defaultOptions: [] #_pp: null #_transitional: true } 4 => Token {#68 ▶} 5 => Concatenation {#69 ▶} 6 => Token {#70 ▶} 7 => Concatenation {#71 ▶} 8 => Choice {#72 ▶} 9 => Concatenation {#73 ▶} 10 => Repetition {#74 ▶} “logical_operation” => Concatenation {#75 ▶} 12 => Token {#66 ▶} 13 => Concatenation {#67 ▶} 14 => Repetition {#78 ▶} “operation” => Concatenation {#79 ▶} 16 => Token {#76 ▶} 17 => Token {#77 ▶} 18 => Concatenation {#82 ▶} “operand” => Choice {#83 ▶} 20 => Token {#80 ▶} 21 => Token {#81 ▼ #_tokenName: “named_parameter” #_namespace: null #_regex: null #_ast: null #_value: null #_kept: true #_unification: -1 #_name: 21 #_children: null #_nodeId: null #_nodeOptions: [] #_defaultId: null #_defaultOptions: [] #_pp: null #_transitional: true } “parameter” => Choice {#86 ▶} 23 => Token {#84 ▶} 24 => Concatenation {#85 ▶} 25 => Token {#89 ▶} 26 => Token {#90 ▶} 27 => Token {#91 ▶} 28 => Token {#92 ▶} 29 => Token {#93 ▶} 30 => Token {#94 ▶} “value” => Choice {#95 ▶} 32 => Token {#87 ▶} 33 => Concatenation {#88 ▶} 34 => Repetition {#98 ▶} “variable” => Concatenation {#99 ▶} 36 => Token {#96 ▶} 37 => Token {#97 ▶} “object_access” => Concatenation {#102 ▶} 39 => Token {#100 ▶} 40 => Token {#101 ▶} 41 => Concatenation {#105 ▶} 42 => Repetition {#106 ▶} 43 => Token {#107 ▶} “array_declaration” => Concatenation {#108 ▶} 45 => Token {#103 ▶} 46 => Token {#104 ▶} 47 => Token {#111 ▶} 48 => Concatenation {#112 ▶} 49 => Repetition {#113 ▶} 50 => Concatenation {#114 ▶} 51 => Repetition {#115 ▶} 52 => Token {#116 ▶} “function_call” => Concatenation {#117 ▶}]然后返回HoaCompilerLlkParser实例,这个实例有一个parse方法,正是此方法构成了一个语法树。public function parse($text, $rule = null, $tree = true) { $k = 1024; if (isset($this->_pragmas[‘parser.lookahead’])) { $k = max(0, intval($this->_pragmas[‘parser.lookahead’])); } $lexer = new Lexer($this->_pragmas); $this->_tokenSequence = new Iterator\Buffer( $lexer->lexMe($text, $this->_tokens), $k ); $this->_tokenSequence->rewind(); $this->_errorToken = null; $this->_trace = []; $this->_todo = []; if (false === array_key_exists($rule, $this->_rules)) { $rule = $this->getRootRule(); } $closeRule = new Rule\Ekzit($rule, 0); $openRule = new Rule\Entry($rule, 0, [$closeRule]); $this->_todo = [$closeRule, $openRule]; do { $out = $this->unfold(); if (null !== $out && ‘EOF’ === $this->_tokenSequence->current()[’token’]) { break; } if (false === $this->backtrack()) { $token = $this->_errorToken; if (null === $this->_errorToken) { $token = $this->_tokenSequence->current(); } $offset = $token[‘offset’]; $line = 1; $column = 1; if (!empty($text)) { if (0 === $offset) { $leftnl = 0; } else { $leftnl = strrpos($text, “\n”, -(strlen($text) - $offset) - 1) ?: 0; } $rightnl = strpos($text, “\n”, $offset); $line = substr_count($text, “\n”, 0, $leftnl + 1) + 1; $column = $offset - $leftnl + (0 === $leftnl); if (false !== $rightnl) { $text = trim(substr($text, $leftnl, $rightnl - $leftnl), “\n”); } } throw new Compiler\Exception\UnexpectedToken( ‘Unexpected token “%s” (%s) at line %d and column %d:’ . “\n” . ‘%s’ . “\n” . str_repeat(’ ‘, $column - 1) . ‘↑’, 0, [ $token[‘value’], $token[’token’], $line, $column, $text ], $line, $column ); } } while (true); if (false === $tree) { return true; } $tree = $this->_buildTree(); if (!($tree instanceof TreeNode)) { throw new Compiler\Exception( ‘Parsing error: cannot build AST, the trace is corrupted.’, 1 ); } return $this->_tree = $tree; }我们得到的一个完整的语法树是这样的:Rule {#120 ▼ #_root: Operator {#414 ▼ #_name: “and” #_arguments: array:2 [▼ 0 => Operator {#398 ▼ #_name: “=” #_arguments: array:2 [▼ 0 => Context {#396 ▼ #_id: “gender” #_dimensions: [] } 1 => Parameter {#397 ▼ -name: “gender” } ] #_function: false #_laziness: false #_id: null #_dimensions: [] } 1 => Operator {#413 ▼ #_name: “and” #_arguments: array:2 [▼ 0 => Operator {#401 ▼ #_name: “>” #_arguments: array:2 [▼ 0 => Context {#399 ▶} 1 => Parameter {#400 ▶} ] #_function: false #_laziness: false #_id: null #_dimensions: [] } 1 => Operator {#412 ▶} ] #_function: false #_laziness: true #_id: null #_dimensions: [] } ] #_function: false #_laziness: true #_id: null #_dimensions: [] }}这里有根节点、子节点、操作符参数以及HoaRulerModelOperator实例。这时$executorModel = $compilationTarget->compile($ast, $context);就可以通过NativeVisitor的visit方法对这个语法树进行访问和分析了。这一步走的是visitOperator() /** * {@inheritdoc} */ public function visitOperator(AST\Operator $element, &$handle = null, $eldnah = null) { $operatorName = $element->getName(); // the operator does not exist at all, throw an error before doing anything else. if (!$this->operators->hasInlineOperator($operatorName) && !$this->operators->hasOperator($operatorName)) { throw new OperatorNotFoundException($operatorName, sprintf(‘Operator “%s” does not exist.’, $operatorName)); } // expand the arguments $arguments = array_map(function ($argument) use (&$handle, $eldnah) { return $argument->accept($this, $handle, $eldnah); }, $element->getArguments()); // and either inline the operator call if ($this->operators->hasInlineOperator($operatorName)) { $callable = $this->operators->getInlineOperator($operatorName); return call_user_func_array($callable, $arguments); } $inlinedArguments = empty($arguments) ? ’’ : ‘, ‘.implode(’, ‘, $arguments); // or defer it. return sprintf(‘call_user_func($operators["%s"]%s)’, $operatorName, $inlinedArguments); }返回的逻辑代码可以通过得到:$executorModel->getCompiledRule() ...

March 4, 2019 · 10 min · jiezi

使用Data URI Scheme优雅的实现前端导出csv

问题描述项目里需要实现一个导出csv的功能,这是个老生常谈的需求,而且我们使用的是iview的组件库,按道理说实现起来应该简单,但实则不然,我在做的时候遇到了一些问题。受限于请求需要token、后端分页、接口、性能等原因不得不放弃iview的导出方式。所以我需要寻找一种可行的、合理的、优雅的导出方案,那就是Data URI Scheme。方案实现方案介绍Data URI Scheme是利用HTML标签的href和src属性来实现的。他看起来像是这样的:<img src=“data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==” alt=“Red dot” />或者<a href=“data:text/csv,something”>download</a>按照这种方案的介绍,我们把要导出的数据拼接在href指定位置就能实现导出的需求,代码实现看起来像这样:<a href="" download=“export.csv” id=“export_csv” style=“display=‘none’">download</a>function export_csv (data) { $(’#export_csv’).href = ‘data:attachment/csv,’ + encodeURI(data); $(’#export_csv’).click(); setTimeout(function () { $(’#export_csv’).href = ‘’; })}export_csv(csv_data_str);测试发现,妥妥的,没毛病。存在问题但在实践中这个方案是有限制的:在chrome的实现中这个url最大限制为2MB。所以,当在Chrome下载的文件大小超过2MB chrome便会报这样的错误(其他浏览器这里不做讨论):下载失败-网络错误这里2MB的大小可以在chromium源码中可以看到:const size_t kMaxURLChars = 2 * 1024 * 1024;…if (!iter->ReadString(&s) || s.length() > url::kMaxURLChars) { *p = GURL(); return false;}变量声明部分源码链接变量引用部分源码链接而关于2MB限制的问题在chromium论坛在2010年就被人作为bug提出来了,但是从2010年一直讨论到2019年也没有明显的改善。方案改进chromium不改,那我们只能自己想办法了,于是有大牛提出来使用URL.createObjectURL + Blob来突破这个限制。借助Blob对象和URL.createObjectURL我们可以得到形如下面的URL:blob:https://xxx.com/0bde569d-20a2-4085-95e6-dcec242962c6这样就能突破Chrome对Data URI Scheme URL大小的限制了。当然呢,我们没用过URL.createObjectURL这个方法,也没用过Blob对象,所以我们要看看浏览的支持情况恩,看起来没有问题,那我们来看看代码实现。<a href=”" download=“export.csv” id=“export_csv” style=“display=‘none’">download</a>function export_csv (data) { const BOM = ‘\uFEFF’; let blob_obj = new Blob([BOM + data], {type: ’text/csv’}); let download_url = URL.createObjectURL(blob_obj); $(’#export_csv’).href = download_url; $(’#export_csv’).click(); setTimeout(function () { // 通过createObjectURL创建的url需要通过revokeObjectURL()来释放 URL.revokeObjectURL(download_url); $(’#export_csv’).href = ‘’; })}export_csv(csv_data_str);恩,这样就不怕超过2MB的CSV的导出了,但是Blob对象有大小限制吗?Good question !我们在chromium的说明文档中可以看到一个表:DeviceRamIn-Memory LimitDiskDisk LimitMin Disk AvailabilityCast512 MB102 MB000Android Minimal512 MB5 MB8 GB491 MB10 MBAndroid Fat2 GB20 MB32 GB1.9 GB40 MBCrOS2 GB409 MB8 GB4 GB0.8 GBDesktop 323 GB614 MB500 GB50 GB1.2 GBDesktop 644 GB2 GB500 GB50 GB4 GB从这个表中,大概可以看出来在In-Memory Storage的时候桌面版64位Chrome Blob的上限为2GB(在Chrome 57似乎上限是500MB)。所以从现在看来这种方法应该是安全的。至此,这个问题算是完整的解决了。iview的实现另外,在我写这篇文章的时候我发现iview的export-csv方法也是按照这个方案实施的,而且做了更多兼容,可以方便大家参考。但他在资源释放的地方做的还需改进,也希望大家注意。参考文档Data protocol URL size limitationsExcellent Export and the Chrome URL limitData_URI_schemeexcellentexport pull request无法在nodejs中下载大文件Issue 69227: Loading large URLs kills the rendererIssue 375297: the total blobs’ size cannot exceed about 500MiBIs there any limitation on JavaScript Max Blob sizechromium/url/url_param_traits.cc#L36chromium/url/url_constants.cc#L32iview 3.x export-csv ...

February 17, 2019 · 1 min · jiezi

Python Pandas读取修改excel操作攻略

环境:python 3.6.8以某米赛尔号举个例子吧:>>> pd.read_excel(‘1.xlsx’, sheet_name=‘Sheet2’) 名字 等级 属性1 属性2 天赋0 四九幻曦 100 自然 None 211 圣甲狂战 100 战斗 None 02 时空界皇 100 光 次元 27我们在这里使用了pd.read_excel()函数来读取excel,来看一下read_excel()这个方法的API,这里只截选一部分经常使用的参数:pd.read_excel(io, sheet_name=0, header=0, names=None, index_col=None, usecols=None)io:很明显, 是excel文件的路径+名字字符串(有中文的话python2的老铁需要使用decode()来解码成unicode字符串) 例如:>>> pd.read_excel(‘例子’.decode(‘utf-8))sheet_name:返回指定的sheet如果将sheet_name指定为None,则返回全表如果需要返回多个表, 可以将sheet_name指定为一个列表, 例如[‘sheet1’, ‘sheet2’]可以根据sheet的名字字符串或索引来值指定所要选取的sheet>>> # 如:>>> pd.read_excel(‘1.xlsx’, sheet_name=0)>>> pd.read_excel(‘1.xlsx’, sheet_name=‘Sheet1’)>>> # 返回的是相同的 DataFrameheader:指定数据表的表头,默认值为0, 即将第一行作为表头usecols:读取指定的列, 也可以通过名字或索引值>>> # 如:>>> pd.read_excel(‘1.xlsx’, sheet_name=1, usecols=[‘等级’, ‘属性1’])>>> pd.read_excel(‘1.xlsx’, sheet_name=1, usecols=[1,2])>>> # 返回的是相同的 DataFrame直到某一天泰格尔升了一级, 可以这样改一下, 当然用.iloc或.loc对象都可以>>> # 读取文件>>> data = pd.read_excel(“1.xlsx”, sheet_name=“Sheet1”)>>> # 找到 等级 这一列,再在这一列中进行比较>>> data[‘等级’][data[‘名字’] == ‘泰格尔’] += 1>>> print(data)LOOK!他升级了!!>>> data 名字 等级 属性1 属性2 天赋0 艾欧里娅 100 自然 冰 291 泰格尔 81 电 战斗 162 布鲁克克 100 水 None 28现在我们将它保存data.to_excel(‘1.xlsx’, sheet_name=‘Sheet1’, index=False, header=True)index:默认为True, 是否加行索引, 直接上图吧!左为False, 右为Trueheader:默认为True, 是否加列标, 上图吧!左为False, 右为True而io, sheet_name参数用法同函数pd.read_excel()如果我们多捕捉几只或者多加几种属性怎么办呢?这里给出参考:新增列数据:data[‘列名称’] = [值1, 值2, ……]>>> data[‘特性’] = [‘瞬杀’, ‘None’, ‘炎火’]>>> data 名字 等级 属性1 属性2 天赋 特性0 艾欧里娅 100 自然 冰 29 瞬杀1 泰格尔 80 电 战斗 16 None2 布鲁克克 100 水 None 28 炎火新增行数据,这里行的num为excel中自动给行加的id数值data.loc[行的num] = [值1, 值2, …], (注意与.iloc的区别)>>> data.loc[3] = [‘小火猴’, 1, ‘火’, ‘None’, 31, ‘None’]>>> data 名字 等级 属性1 属性2 天赋 特性0 艾欧里娅 100 自然 冰 29 瞬杀1 泰格尔 80 电 战斗 16 None2 布鲁克克 100 水 None 28 炎火3 小火猴 1 火 None 31 None说完了增加一行或一列,那怎样删除一行或一列呢?可以使用.drop()函数>>> # 删除列, 需要指定axis为1,当删除行时,axis为0>>> data = data.drop(‘属性1’, axis=1) # 删除属性1列>>> data 名字 等级 属性2 天赋 特性0 艾欧里娅 100 冰 29 瞬杀1 泰格尔 80 战斗 16 None2 布鲁克克 100 None 28 炎火3 小火猴 1 None 31 None>>> # 删除第3,4行,这里下表以0开始,并且标题行不算在类, axis用法同上>>> data = data.drop([2, 3], axis=0)>>> data 名字 等级 属性2 天赋 特性0 艾欧里娅 100 冰 29 瞬杀1 泰格尔 80 战斗 16 None>>> # 保存>>> data.to_excel(‘2.xlsx’, sheet_name=‘Sheet1’, index=False, header=True)大家具体可以参考官网提供的API:http://pandas.pydata.org/pand… ...

February 17, 2019 · 2 min · jiezi

前端js实现字符串/图片/excel文件下载

在web开发中,如果你想让用户下载或者导出一个文件,应该怎么做呢?传统的做法是在后端存储或者即时生成一个文件来提供下载功能,这样的优势是可以做权限控制、数据二次处理,但缺点是需要额外发起请求、增大服务端压力、下载速度慢。但随着HTML5的标准发布,我们已经能够做到只前端来下载各种文件了。<a>标签的download属性此属性指示浏览器下载URL而不是导航到它,因此将提示用户将其保存为本地文件。如果属性有一个值,那么它将作为下载的文件名使用。此属性对允许的值没有限制,但是/和\会被转换为下划线。此属性仅适用于同源 URLs。尽管HTTP URL需要位于同一源中,但是可以使用 blob: URLs 和 data: URLs ,以方便用户下载 JavaScript 方式生成的内容(例如使用在线绘图的Web应用创建的照片)。常规的<a>标签,用于链接的跳转,如新的页面,那么如果我们给<a>标签加上download属性,就能很简单的让用户保存新的html页面。<a download=“PHP实现并发请求.html” href=“https://segmentfault.com/a/1190000016343861">PHP实现并发请求</a>生成并下载字符串文件首先我们需要了解一个特殊的数据格式:Blob。Blob数据Blob(Binary Large Object,二进制类型的大对象),表示一个不可变的原始数据的类文件对象,我们上传文件时常用的File对象就继承于Blob,并进行了扩展用于支持用户系统上的文件。我们只能通过Blob()构造函数来创建一个新的Blob对象:Blob(blobParts[, options])// 创建一个json类型的Blob对象,支持传入同类型数据的一个数组var debug = {hello: “world”};var blob = new Blob([JSON.stringify(debug, null, 2)], {type : ‘application/json’});// 此时blob的值// Blob(22) {size: 22, type: ‘application/json’}Blob对象存在两个只读属性:size: Blob 对象中所包含数据的大小(字节)。type: 一个字符串,表明该Blob对象所包含数据的MIME类型。如果类型未知,则该值为空字符串。URL对象和下载字符串文件URL 接口是一个用来创建 URLs 的对象,包含两个静态方法:objectURL = URL.createObjectURL(blob)创建一个 URL(DOMString),包含一个唯一的blob链接(该链接协议为以blob:,后跟唯一标识浏览器中的对象的掩码)。这个 URL 的生命周期和创建它的窗口中的 document 绑定。URL.revokeObjectURL(objectURL)销毁之前使用URL.createObjectURL()方法创建的URL实例。浏览器会在文档退出的时候自动释放它们,但是为了获得最佳性能和内存使用状况,你应该在安全的时机主动释放掉它们。var url = URL.createObjectURL(blob);// 此时url的值,跟document绑定,所以每个页面创建的字符串均不同// blob:https://developer.mozilla.org/defe53c2-2882-43c6-b275-db2a57959789此时,我们在页面中创建一个新<a>标签,点击即可下载我们想要的文件:<a href=“blob:https://developer.mozilla.org/58702010-433d-4097-990f-e483d84cd02a” download=“file.json”>下载文件链接</a>FileReader读取Blob数据想要读取Blob数据的唯一方法是FileReader。FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。其中File对象可以是来自用户在一个<input>元素上选择文件后返回的FileList对象,也可以来自拖放操作生成的 DataTransfer对象,还可以是来自在一个HTMLCanvasElement上执行mozGetAsFile()方法后返回结果。该对象包含3个属性:FileReader.error一个DOMException,表示在读取文件时发生的错误 。FileReader.readyState表示FileReader状态的数字。取值如下:常量名 值 描述EMPTY 0 还没有加载任何数据.LOADING 1 数据正在被加载.DONE 2 已完成全部的读取请求.FileReader.result文件的内容。该属性仅在读取操作完成后才有效,数据的格式取决于使用哪个方法来启动读取操作。包含6个事件处理:onabort,onerror,onload,onloadstart,onloadend,onprogress,这些不再详细说明,因为 FileReader 继承自EventTarget,所以所有这些事件也可以通过addEventListener方法使用。包含5个方法:FileReader.abort()中止读取操作。在返回时,readyState属性为DONE。FileReader.readAsArrayBuffer()开始读取指定的 Blob中的内容, 一旦完成, result 属性中保存的将是被读取文件的 ArrayBuffer 数据对象.FileReader.readAsBinaryString() 开始读取指定的Blob中的内容。一旦完成,result属性中将包含所读取文件的原始二进制数据。FileReader.readAsDataURL()开始读取指定的Blob中的内容。一旦完成,result属性中将包含一个data: URL格式的字符串以表示所读取文件的内容。FileReader.readAsText()开始读取指定的Blob中的内容。一旦完成,result属性中将包含一个字符串以表示所读取的文件内容。因此我们可以直接读取Blob对象的数据:var reader = new FileReader();reader.addEventListener(“loadend”, function() { console.log(reader.result);});reader.readAsDataURL(blob);// 此时result的值// data:application/json;base64,ewogICJoZWxsbyI6ICJ3b3JsZCIKfQ==reader.readAsText(blob);// 此时result的值// {// “hello”: “world”// }下载图片除了下载手动生成的字符串或对象,我们还能提供下载图片的功能,一方面能用于支持Canvas绘图的保存功能,一方面能提供批量下载图片等高级功能。除了浏览器自带的右键保存,我们还可以这么做来下载图片:// 通过src获取图片的blob对象function getImageBlob(url, cb) { var xhr = new XMLHttpRequest(); xhr.open(“get”, url, true); xhr.responseType = “blob”; xhr.onload = function() { if (this.status == 200) { cb(this.response); } }; xhr.send();}let reader = new FileReader();reader.addEventListener(“loadend”, function() { console.log(reader.result);});getImageBlob(‘https://cdn.segmentfault.com/v-5c4ec07f/global/img/user-64.png', function(blob){ // 读取来看下下载的内容 reader.readAsDataURL(blob); // 最终生成的字符串 // data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAA… // 生成下载用的URL对象 let url = URL.createObjectURL(blob); // 生成一个a标签,并模拟点击,即可下载,批量下载同理 let aDom = aDom = document.createElement(‘a’); aDom.href = url; aDom.download = ‘download.json’; aDom.text = ‘下载文件’; document.getElementsByTagName(‘body’)[0].appendChild(aDom); aDom.click();});下载excel文件等如果你明白了下载的原理,那么所有的内容都能够理解,只不过是转换成对应的格式而已,当然,复杂格式的文档不需要你自己去配置,可以引入第三方库,在excel文档方面我选择用 tableExport库:// 引入CDN文件’https://cdn.bootcss.com/xlsx/0.14.1/xlsx.core.min.js','https://cdn.bootcss.com/FileSaver.js/2014-11-29/FileSaver.min.js','https://cdn.bootcss.com/TableExport/5.2.0/js/tableexport.min.js'// 绑定下载事件,这个是我自己的场景下代码,可能不适合大家,具体的参考官方文档const tableDom = $(’#table’);$(’.table-exportBtn’, tableDom).on(‘click’, function () { const tableExport = tableDom.tableExport({ formats: [‘xlsx’, ’txt’], filename: ‘表格下载’, exportButtons: false }); const type = $(this).data().type; const exportData = tableExport.getExportData()[tableDom[0].id][type]; const {data, mimeType, filename, fileExtension} = exportData; tableExport.export2file(data, mimeType, filename, fileExtension);});参考资料MDN-a: https://developer.mozilla.org…MDN-blob: https://developer.mozilla.org…掘金-细说Web API中的Blob:https://juejin.im/post/59e35d…MDN-URL: https://developer.mozilla.org…MDN-FileReader: https://developer.mozilla.org…博客园-js 获取图片url的Blob值并预览:https://www.cnblogs.com/tujia…tableExport文档:https://tableexport.v5.travis… ...

February 13, 2019 · 1 min · jiezi

[SheetJS] js-xlsx模块学习指南

简介SheetJS是前端操作Excel以及类似的二维表的最佳选择之一,而js-xlsx是它的社区版本.js-xlsx将注意力集中到了数据转换和导出上,所以它支持相当多种类的数据解析和导出.不仅仅局限于支持xlsx格式.支持的导入格式支持的导出格式它可以:解析符合格式的数据导出符合格式的数据利用中间层操作数据可以运行在:浏览器端Node端浏览器端特色纯浏览器端解析数据纯浏览器端导出数据Node端特色读写文件流式读写本篇文章力求精简,主要讨论一下js-xlsx的工作流程和基本概念以及使用方式.概念js-xlsx提供了一个中间层用于操作数据,他将不同类型的文件抽象成同一个js对象,从而规避了操作不同种类数据数据之间的复杂性.并且围绕着这个对象提供了一系列的抽象功能,本小节主要讨论这些数据对象与Excel数据之间的关系.而浏览器端和Node端的区别仅仅在于怎样导入文件和导出文件上而已,对于数据的操作,双方的接口是一致的.引入js-xlsx的引入非常简单,浏览器端引入可以是最基本script标签的形式.<script lang=“javascript” src=“dist/xlsx.full.min.js”></script>在node端,使用npm安装如下模块:npm install xlsx –save在Node中如下引入:const xlsx = require(‘xlsx’);详细文档地址对应关系在这个表格中我列举了Excel与js-xlsx之间的关系:Excel名词js-xlsx中的抽象类型工作簿workBook工作表SheetsExcel引用样式(单元格地址)cellAddress单元格cell有了这个基本的对应关系我们就可以轻松的理解后续的操作,例如在我们使用Excel的过程中,获取一个数据的流程如下:打开工作簿打开一个工作表选中一片区域或者一个单元格针对数据进行操作保存(另存为)那么在js-xlsx中获取一个单元格内容的操作如下:// 先不要关心我们的workbook对象是从哪里来的var first_sheet_name = workbook.SheetNames[0]; // 获取工作簿中的工作表名字var address_of_cell = ‘A1’; // 提供一个引用样式(单元格下标)var worksheet = workbook.Sheets[first_sheet_name]; // 获取对应的工作表对象var desired_cell = worksheet[address_of_cell]; // 获取对应的单元格对象var desired_value = (desired_cell ? desired_cell.v : undefined);// 获取对应单元格中的数据数据格式图片:工作簿的数据结构一旦我们的Excel文件被解析那么这个Excel表中的所有内容都会被解析上面的这个对象.而且这整个过程是同步完成的.所以我们可以使用键的方式来直接获取数据,在上面的例子中我们就利用键一层层的向下获取数据.上图中常用的键一共有两个:SheetNames以字符串数组的形式保存了所有的工作表的名称Sheets下的内容都是工作表对象,而键名就是SheetNames中包含的名字而Excel的数据单位由小到大有如下排序如下:单元格工作表工作簿单元格格式在Excel中单元格有多种格式,而js-xlsx会将其解析为对应的JavaScript的格式.常见格式如下:键描述v源数据(未经处理的数据)w格式化后的文本(如果能够被格式化)t单元格类型(具体类型请看下方的表格)r解码后的富文本(如果可以被解码)h渲染成HTML格式的富文本(如果可以被解码)c单元格注释z格式化成字符串的数值(如果需要的话)完整格式链接.解析后单元格数据格式:这个数据在Excel中保存在A1的位置上,文本类型,单元格内容为xm.单元格地址js-xlsx使用有两种方式来描述操作中的单元格区域.一种是单元格地址对象(Cell address object)另外一种是地址范围(Cell range).地址对象格式如下:const start = { c: 0, r: 0 };const end = { c: 1, r: 1 };上方地址对象对应的地址范围如下:const range = ‘A1:B2’;我们不难发现两者之间对应的关系:地址对象描述的是一个起始坐标(从0开始)到结束坐标之间的范围.地址范围就是Excel中的引用样式.注意:这两个概念会在工作表读写中使用到.APIjs-xlsx提供的接口非常清晰主要分为两类:xlsx对象本身提供的功能解析数据导出数据utils工具类将数据添加到数据表对象上将二维数组以及符合格式的对象或者HTML转为工作表对象将工作簿转为另外一种数据格式行,列,范围之间的转码和解码工作簿操作单元格操作读取数据并解析这里提供一个简单的Node例子(Node10+):const xlxs = require(‘xlsx’);const {readFile} = require(‘fs’).promises;(async function (params) { // 获取数据 const excelBuffer = await readFile(’./books.xlsx’); // 解析数据 const result = xlxs.read(excelBuffer,{ type:‘buffer’, cellHTML:false, }); console.log(‘TCL: result’, result);})();还可以使用utils.book_new()创建一个新的工作簿对象:const xlsx = require(‘xlsx’), { utils } = xlsx;const workBook= utils.book_new(); // 创建一个工作簿然后使用跟多的工具来操作工作簿对象:// 接着上面的例子const ws_data = [ [ “S”, “h”, “e”, “e”, “t”, “J”, “S” ], [ 1 , 2 , 3 , 4 , 5 ]];const workSheet = XLSX.utils.aoa_to_sheet(ws_data);// 使用二维数组创建一个工作表对象utils.book_append_sheet(workBook,workSheet,‘工作表名称’);// 向工作簿追加一个工作表console.log(workBook);详细的解析文档详细解析选项数据填充工作表是实际存放数据的地方,在大部分情况下我们的操作都是对于工作表对象的操作.js-xlsx提供了多种方式来操作数据,这里提供最常见的几种操作:利用现有的数据结构创建工作表二维数组作为数据源JSON作为数据源修改工作表数据二维数组作为数据源JSON作为数据源创建工作表const workSheet = utils.aoa_to_sheet([[1,2,3,new Date()],[1,2,,4]],{ sheetStubs:false, cellStyles:false, cellDates:true // 解析为原生时间});console.log(workSheet);二维数组的关系非常容易理解,数组中的每一个数组代表一行.图片:二维数组结果const workSheet = utils.json_to_sheet([{ ‘列1’: 1, ‘列2’: 2, ‘列3’: 3 },{ ‘列1’: 4, ‘列2’: 5, ‘列3’: 6 }],{ header:[‘列1’,‘列2’,‘列3’], skipHeader:true// 跳过上面的标题行})console.log(workSheet);图片:JSON效果详细文档地址修改数据表数据const workSheet = utils.json_to_sheet([{ ‘列1’: 1, ‘列2’: 2, ‘列3’: 3 },{ ‘列1’: 4, ‘列2’: 5, ‘列3’: 6 }],{ header:[‘列1’,‘列2’,‘列3’], skipHeader:true// 跳过上面的标题行})utils.sheet_add_aoa(workSheet,[ [7,8,9], [‘A’,‘B’,‘C’]],{ origin:‘A1’ // 从A1开始增加内容});console.log(workSheet);图片:二维数组结果const workSheet = utils.json_to_sheet([{ ‘列1’: 1, ‘列2’: 2, ‘列3’: 3 },{ ‘列1’: 4, ‘列2’: 5, ‘列3’: 6 }],{ header:[‘列1’,‘列2’,‘列3’], skipHeader:true// 跳过上面的标题行})utils.sheet_add_json(workSheet,[ { ‘列1’: 7, ‘列2’: 8, ‘列3’: 9 }, { ‘列1’: ‘A’, ‘列2’: ‘B’, ‘列3’: ‘C’ }],{ origin:‘A1’,// 从A1开始增加内容 header: [‘列1’, ‘列2’, ‘列3’], skipHeader: true// 跳过上面的标题行});console.log(workSheet);图片:JSON效果详细文档地址数据导出数据导出分为两个部分:利用工具类将工作簿对象转为其他数据结构调用write或者writeFile方法转换为其他的数据结构这里就不提供详细的用例了,可以转换的格式如下:详细文档地址输出文件这里提供一个简单的Node例子(Node10+):const xlsx = require(‘xlsx’), { utils } = xlsx;const {writeFile} =require(‘fs’).promises;const workBook= utils.book_new();const workSheet = utils.aoa_to_sheet([[1,2,3]],{ cellDates:true,});// 向工作簿中追加工作表utils.book_append_sheet(workBook, workSheet,‘helloWorld’);// 浏览器端和node共有的API,实际上node可以直接使用xlsx.writeFile来写入文件,但是浏览器没有该APIconst result = xlsx.write(workBook, { bookType: ‘xlsx’, // 输出的文件类型 type: ‘buffer’, // 输出的数据类型 compression:true // 开启zip压缩});// 写入文件writeFile(’./hello.xlsx’,result).catch((error)=>{ console.log(error);});write方法文档以及输出选项支持的输出文件格式引用https://github.com/SheetJS/js… ...

January 31, 2019 · 2 min · jiezi

R 脚本读取汇总 Excel 表格数据

主要用到了 xlsx 和 rJava 包,打开 Excel 文件,读取各表格数据,再写入到汇总表。下图为处理前的原始数据表格:下图为处理后的数据:代码实现安装&加载包的函数实现。installed.packages() 函数获取所有已安装的包,用以排除已安装的包。install.packages() 函数安装指定的包。library() 加载引入包。loadLibrary <- function(pkgs) { uninstalledPkgs <- pkgs[!(pkgs %in% installed.packages()[, “Package”])] if (length(uninstalledPkgs)) { install.packages(uninstalledPkgs) } for (pkg in pkgs) { library(pkg, character.only = TRUE, quietly = TRUE) }}自定义设置。涉及表格文件路径、汇总表名等。setwd("/path/to/work/dir") # 工作目录fileName = “summary_sheet_demo.xlsx” # 处理的表格文件summaryName = “汇总” # 汇总的 sheet 表名summarySheet = FALSE # 对象变量、忽略startRow = 2 # 汇总表中操作起始行设置 CRAN 源。官方默认源可能比较慢,所以选择国内的源很重要。此处选择了清华 CRAN 源,其他的可参考 CRAN Mirrors。options(repos = “https://mirrors.tuna.tsinghua.edu.cn/CRAN/")加载依赖包。用到了上述写的安装加载包的函数。loadLibrary(c(“xlsx”, “rJava”))打开工作表。loadWorkbook() 打开指定路径的表格文件,并加载到工作簿对象中。wb <- loadWorkbook(fileName)遍历查询&汇总数据。# 获取所有表格sheets <- getSheets(wb)# 循环所有表格,找出需要写入的表for (sheet in sheets) { sheetName <- sheet$getSheetName() if (sheetName == summaryName) { summarySheet <- sheet }}if (summarySheet == FALSE) { stop(paste(“表:”, summaryName, “未找到”))}# 指定Date格式(此处可忽略)# options(xlsx.date.format=‘yyyy/MM/dd’)# 遍历所有表格for (sheet in sheets) { # 过滤掉需写入的表 sheetName <- sheet$getSheetName() if (sheetName == summaryName) { next } # 获取表格【内容行数】 rowNum <- sheet$getLastRowNum() print(paste(“表名:”, sheetName, “总共:”, rowNum, “行,”, sep = " “)) # 读取表格内容 参数 colClasses 指定每列的类型(实际是指定处理该列的类/对象) data <- read.xlsx2(fileName, sheetName = sheetName, header = FALSE, startRow = 2, colClasses = c(“character”, “Date”, “integer”, “integer”, rep(“numeric”, 2), “integer”)) print(data) # 将表格内容写入汇总的那张表 addDataFrame(data, summarySheet, col.names = FALSE, row.names = FALSE, startRow = startRow) # 累加行数 startRow <- startRow + rowNum}把对象内容写入文件中保存。saveWorkbook(wb, fileName)完整代码# 包加载/安装包loadLibrary <- function(pkgs) { uninstalledPkgs <- pkgs[!(pkgs %in% installed.packages()[, “Package”])] if (length(uninstalledPkgs)) { install.packages(uninstalledPkgs) } for (pkg in pkgs) { library(pkg, character.only = TRUE, quietly = TRUE) }}# 自定义配置setwd("/path/to/work/dir”) # 工作目录fileName = “summary_sheet_demo.xlsx” # 处理的表格文件summaryName = “汇总” # 汇总的 sheet 表名summarySheet = FALSE # 对象变量、忽略startRow = 2 # 汇总表中操作起始行# 设置CRANoptions(repos = “https://mirrors.tuna.tsinghua.edu.cn/CRAN/")# 加载依赖包loadLibrary(c(“xlsx”, “rJava”))# 打开Excel表格wb <- loadWorkbook(fileName)# 获取所有表格sheets <- getSheets(wb)# 循环所有表格,找出需要写入的表for (sheet in sheets) { sheetName <- sheet$getSheetName() if (sheetName == summaryName) { summarySheet <- sheet }}if (summarySheet == FALSE) { stop(paste(“表:”, summaryName, “未找到”))}# 指定Date格式(此处可忽略)# options(xlsx.date.format=‘yyyy/MM/dd’)# 遍历所有表格for (sheet in sheets) { # 过滤掉需写入的表 sheetName <- sheet$getSheetName() if (sheetName == summaryName) { next } # 获取表格【内容行数】 rowNum <- sheet$getLastRowNum() print(paste(“表名:”, sheetName, “总共:”, rowNum, “行,”, sep = " “)) # 读取表格内容 参数 colClasses 指定每列的类型(实际是指定处理该列的类/对象) data <- read.xlsx2(fileName, sheetName = sheetName, header = FALSE, startRow = 2, colClasses = c(“character”, “Date”, “integer”, “integer”, rep(“numeric”, 2), “integer”)) print(data) # 将表格内容写入汇总的那张表 addDataFrame(data, summarySheet, col.names = FALSE, row.names = FALSE, startRow = startRow) # 累加行数 startRow <- startRow + rowNum}# 最后需要把对象内容写入文件中saveWorkbook(wb, fileName)表格附件summary_sheet_demo.xlsx原文地址: https://shockerli.net/post/r-…更多文章请访问我的个人博客: https://shockerli.net ...

January 25, 2019 · 2 min · jiezi

Java 嵌入 SPL 轻松实现 Excel 文件合并

大多数JAVA程序猿都选择使用POI或者HSSFWorkbook等第三方类库来实现Excel自动化合并,这样一来不仅需要噼里啪啦的敲好多代码,费事费力,而且用起来灵活度也不高,对Excel的格式要求也很严格。如果能有一个专用的外部数据工具,写简单类似SQL的脚本来实现,然后在JAVA中直接调用并返回结果集,就再好不过了。润乾集算器就是这样的机制,通过使用JDBC调用SPL脚本,使用起来方便快捷,下面就来学习下具体如何使用。SPL实现常规合并:A. 同一个 excel 中的多个Sheet表合并下面的例子是一个包含了销售数据的 excel 文件,其中包含了按月划分的 3 个结构相同的 sheet 工作表,数据如下:January_2013:February_2013:March_2013:在合并3个Sheet的同时,我们还可以同时从每个sheet中筛选出字段Customer Name, Sale Amount。最后的效果如下:SPL脚本:保存脚本文件oneExcel.dfx(嵌入Java会用到)脚本说明:A1: 打开指定的 excel 文件,创建一个由多个 sheet 工作表组成的序列。A2:利用 conj 函数遍历 A1 序列中所有的成员工作表,导入每个工作表中指定列’Customer Name’,‘Sale Amount’,并将数据并合并。其中 xlsimport 函数导入指定列,最后一列用分号; 隔开。 参数~.stname表示指定当前工作表,由于在 conj 函数的循环中,所以就可以逐个导入所有工作表。同时,xlsimport 使用选项@t指明将工作表的第一行记录作为字段名。A3:将序表 A2 作为一个新的工作表“merge_sheets”保存到原来的 excel 文件中,同样用选项 @t 指明首行记录为标题。这段脚本只有三句话,短小精干之余,逻辑清晰,也比较容易理解。下面我们再看看如何合并多个文件中的多个工作表。B. 不同 excel 中的多表合并下面是要合并的多个 excel 文件,它们都具有和上面例子相同的表结构,每个文件记录了当年的数据: SPL脚本:合并后的结果如下:保存脚本文件MergeExcels.dfx(嵌入Java会用到)脚本说明:A1: 通过 for 循环,遍历指定目录下的 excel 文件,在 B1 到 B3 之间进行循环内处理。B1:打开目录下的一个 excel 文件,生成序列。B2:导入当前文件中的每个 sheet 工作表中指定列’Customer Name’,‘Sale Amount’,‘Purchase Date’的数据,然后合并这些数据,与前面例子中的 A2 类似。B3:将序表 B2 的数据与 @表示的本网格的值进行合并。A4:将序表 B3 保存到result.xlsx文件中的 merge_data 工作表中。上面程序用两个循环就实现了多个 excel 文件数据合并,外循环 for 遍历了目录下所有的 excel 文件,内循环B1.conj则合并每个excel文件中的多个sheet工作表的数据。C. 合并出大文件前面第一个例子中的 A2、第二个例子中的 B3 都是在内存中装载了合并后的 Excel 的所有数据,然后一次性写出。如果文件太多太大,那么对内存的占用也会很大,甚至超出内存允许的范围。为此,我们可以在SPL脚本中采用流式追加的方式生成大文件。SPL脚本:合并后的效果如下:保存脚本文件BigExcel.dfx(嵌入Java会用到)脚本说明:A1:打开指定输出的文件。A2:遍历目录下需要合并的 excel 文件。B2:打开一个需要合并的 excel 文件。B3:如果输出文件不存在,读取 sheet 工作表的所有数据,包括标题行;如果输出文件已经有了,就通过 @t 选项指明第一行是标题,从第二行开始读取数据。B4:将 B3 读取的数据以流式追加到 A1 指定的输出文件的 merger 工作表中。通过流式逐个读取文件数据后追加写入,这个方式适合将大量小的 excel 文件合并成一个大的 excel 文件。JAVA调用SPL嵌入到Java应用程序十分方便,通过JDBC调用存储过程方法加载,用同一个excel中的多个Sheet表合并保存的文件OneExcel.dfx,示例调用如下:… Connection con = null; Class.forName(“com.esproc.jdbc.InternalDriver”); con= DriverManager.getConnection(“jdbc:esproc:local://”);//调用存储过程,其中OneExcel是dfx的文件名 st =(com. esproc.jdbc.InternalCStatement)con.prepareCall(“call OneExcel()”);//执行存储过程 st.execute();//获取结果集 ResultSet rs = st.getResultSet(); … 替换成MergeExcels.dfx/BigExcel.dfx是同样的道理,只需call MergeExcels()或者call BigExcel()即可。这里只用 Java 片段粗略解释了如何嵌入 SPL,详细步骤请参阅Java 如何调用 SPL 脚本,也非常简单,不再赘述。同时,SPL 也支持 ODBC 驱动,集成到支持 ODBC 的语言,嵌入过程类似。拓展节选关于Excel文件的处理除了像上面讲的普通合并外,还可以在SPL脚本中对汇总后的结果分组去重,然后再将结果集导出。分组汇总下面继续以前面的销售数据 excel 文件为例。 A. 字段分组根据某个字段或多个字段实现分组计算,SPL 脚本如下:A3的效果: A4的效果:脚本说明:A1: 打开指定的 excel 文件。A2:读取并合并文件中所有 sheet 工作表的数据。A3:在合并后的数据上按字段 ‘Customer ID’ 分组求销售额、平均值。A4:在合并后的数据上按字段 ‘Customer ID’, ‘Purchase Date’ 分组求销售额。B. 按序分组集算器在进行分组聚合时还可以和相邻数据行对比,在原数据已经有序时可以不再排序,从而节省时间,并保持原有的次序。假设原数据已经按日期排序,我们想按月份分组统计时,代码如下。SPL 脚本:A5 分组效果:A6 分组效果:脚本说明:A1至B3: 在前面的例子中已经介绍,将同一目录下所有相同结构的 excel 文件的工作表进行合并。A4:在序表 B3 的基本上重新构造了一个序表 A4,将日期拆分,新增年、月字段。A5:groups 跨年度按月分组汇总销售额、平均值。A6:groups@o 按年月分组汇总销售额、平均值, 带参数 @o 实现分组归并处理。其中,A4 为数据记录明细;A5 按月统计, 不区分年;A6 则按年月统计。这三个单元格中的数据展现出了不同层次的合并汇总结果。C. 分段分组将要统计的数据按条件分成几段,统计各组的情况。SPL 脚本:分组效果:代码说明:步骤A1到 B3 之间参考前面例子的说明。A4:字段’Sale Amount’金额的范围分成 5 段,然后累计求出各段的数量及总数。不过,这样的写法不够方便,如果我们想调整分段方案,就需要修改 groups 函数的参数,而这个参数表达式还是比较复杂的。这时,我们还可以利用集算器中另一个 pseg 函数,更方便地实现这个功能,脚本如下:当然,我们也可以根据需要,按不同字段不同要求进行分组,然后进行统计处理。例如,在统计班级考生成绩时,各科成绩可划分成优、良、中、差、及格的分数区段,一次为条件进行统计。groups 用法还有很多,可以参考函数手册中相应的章节。D. 大数据分组前面的例子中,要读取的 excel 文件都不能很大,也就是都能一次读进内存。手工处理大文件,也会有类似的要求,因为同时打开多个文件,意味着把这些文件都装入内存,很可能会超过机器的物理内存,而用 VBA 读取的情况也差不多。这时,我们就需要用流式的方法读取数据,不需一次读进内存,而是边读取边合并。 SPL 脚本:筛选分组的效果:代码说明:A1: 使用 @r 选项指明以流式打开 excel 文件。A2:遍历 excel 中的 sheet 工作表。B2:使用 @c 选项指明以游标方式导入数据。B3:将游标B2汇集到B3序列中。A4:将游标序列B3的成员合并到一起组成新的游标。B4:序列A4按‘Customer ID’分组累计‘Sale Amount’。A5:将结果保存。通过游标以流的方式循环从大文件中读取一段段数据,实现对数据的分组合并。去重处理实际数据合并过程中,往往会出现数据重复的现象,重复数据肯定会影响到我们对数据的计算分析。下面介绍使用集算器 SPL 脚本去除重复数据的几种主要解决方法。A. 主键去重sales_2013中的数据,设其主键为’Invoice Number’,则根据主键去掉重复记录。合并去重后的数据:代码说明:A1: 打开指定的 excel 文件。A2:导入 sheet 工作表中指定列的数据。A3:将序表 A2 按主键’Invoice Number’分组去重处理, 其中参数 @1 表示取每一个分组的第一条记录组成排列后返回(注意是数字 1,不是字母 l)。A4:将结果保存。各个 sheet> 中的数据是唯一的,但合并的数据不一定是唯一的,因此采用主键方式去掉重复数据。B. 某字段去重根据数据表 sales_2013 中的某字段去重处理, 查看不同姓名的雇员记录.代码说明:A1: 打开指定的 excel 文件。A2:导入 sheet 工作表中指定列的数据。A3:从序表 A2 中获取不重复姓名的记录。A4:从序表 A2中获取不重复姓名的记录列表。A5:将序表 A4 另存,首行记录为标题。A3 数据去重结果:A4 数据去重结果:C. 联合多字段去重有的记录虽然有主键,但判断是否为重复的记录,需要用其它几个字段来确定,此时用多个字段联合来确定是否有重复记录.代码说明:A1: 导入指定 excel 文件的数据。A2:同上。A3:按字段 ‘Customer ID’, ‘Purchase Date’ 合并序表 A1,A2,返回序表 A3。A4:序表 A3 按 ‘Customer ID’, ‘Purchase Date’ 分组去重。A5:将结果保存。当然,也可以根据需要,参考更多的字段进行分组合并,去掉重复记录。D. 记录级去重解决要合并的每个文件中的记录本身是不重复的,但合并后可能存在重复记录。代码说明:A1: 导入 excel 文件的数据。B1:根据字段’Invoice Number’去掉序表 A1中的重复数据。A2、B2:同上A3:合并序表 B1,B2 的数据,并去掉重复数据记录返回序表 A3。选项 @u 表示序表成员按顺序合并到一起组成新的序表, 去掉重复的记录。B3:查看合并后的数据记录数。merge@u适合对多序表合并处理, 其中序表内部有序且无重复数据。总结使用SPL处理同构/异构excel 多文件合并、分组汇总数据及数据去重时,都是只要把需要合并的字段读成集算器的集合对象就可以了。学会了用这种专业数据处理工具,不仅能合并 Excel 文件, 合并其他文本数据方法也是一致的,再也不用担心合并数据中的多文件、大文件和结构差异问题了。SPL优势有库写 SQL,没库写 SPL用Java程序直接汇总计算数据,还是比较累的,代码很长,并且不可复用,很多情况数据也不在数据库里,有了SPL,就能像在Java中用SQL一样了,十分方便。常用无忧,不花钱就能取得终身使用权的入门版如果要分析的数据是一次性或临时性的,润乾集算器每个月都提供免费试用授权,可以循环免费使用。但要和Java应用程序集成起来部署到服务器上长期使用,定期更换试用授权还是比较麻烦,润乾提供了有终身使用权的入门版,解决了这个后顾之忧,获得方式参考如何免费使用润乾集算器?技术文档和社区支持官方提供的集算器技术文档本身就有很多现成的例子,常规问题从文档里都能找到解决方法。如果获得了入门版,不仅能够使用SPL的常规功能,碰到任何问题都可以去乾学院上去咨询,官方通过该社区对入门版用户提供免费的技术支持。 ...

January 23, 2019 · 2 min · jiezi

Excel常用函数公式TOP6(下)

正如我们所知,Excel在数据分析中是一个必不可少的工具,不管是分析师、业务还是运营人员,最常用到的工具软件非Excel莫属,接下来介绍一下在Excel中较为常用的一些函数公式。1.vlookup—条件查找函数用法:=vlookup(要查找的目标,查找范围,返回第几列的内容,精确或者近似结果)PS:查找值必须在返回值的前面。2.lookup—多条件查找函数用法:=lookup(1,0/((条件区域1=条件1)*(条件区域2=条件2)),查找目标的区域)3.mid—提取字符串函数用法:=mid(原始字符串,提取的字符串开始的位置,提取的字符串的长度)4.substitute—替换字符串函数用法:=substitute(要替换的文本,旧文本,新文本,[替换第几个])5.round—四舍五入函数用法:=round(需要四舍五入的数字,想要保留的小数位数)6.randbetween—生成随机数函数用法:=randbetween(数字下限,数字上限)

January 20, 2019 · 1 min · jiezi

Excel常用函数公式TOP6(上)

正如我们所知,Excel在数据分析中是一个必不可少的工具,不管是分析师、业务还是运营人员,最常用到的工具软件非Excel莫属,接下来介绍一下在Excel中较为常用的一些函数公式。1.if函数—条件判断函数用法:=if(需要判断的条件,“符合条件想返回的结果”,“不符合条件想返回的结果”)2.if+and—多条件判断函数用法:=if(and(条件1,条件2),“符合条件想返回的结果”,“不符合条件想返回的结果”)3.sumif—条件求和函数用法:=sumif(条件区域,指定的求和条件,求和区域)4.sumifs—多条件求和函数用法:=sumifs(求和的区域,条件区域1,指定求和条件1,条件区域2,指定求和条件2,……)5.countif—条件计数函数用法:=countif(条件区域,指定条件)6.countifs—多条件计数函数用法:=countifs(条件区域1,指定条件1,条件区域2,指定条件2)这次先介绍这几个常用的函数,下次继续更新~

January 18, 2019 · 1 min · jiezi

怎样用 Excel 快速做数据分析?

CDA数据分析研究原创作品, 转载需授权excel不仅是一个数据存储工具,还是一个简单的数据分析工具,添加EXCEL数据分析插件后,可以做一些简单相关、回归等分析。那么如何添加EXCEL数据分析插件呢?以office2016专业增强版为例,具体操作演示如图所示。首先,新建并打开excel表格。添加数据分析插件,点击“文件”功能,在弹出的对话框中选择“选项”功能。在弹出的对话框中点击“加载项”选项,选中“分析工具库”,点击下方"转到"按钮。然后出现excel加载宏界面,在”分析工具库“前方框内打勾,点击确定。添加成功,在”数据“-”数据分析“下显示。点击”数据分析“,会显示相关的分析方法,如 回归分析,方差分析,相关分析等。EXCEL数据分析插件已经添加完成,接下来我们用EXCEL数据分析的数据分析功能做一个简单的线性回归分析。一元线性回归是分析两个变量之间的因果关系的,下面我们要研究CDA学员的学历对就业薪资是否有影响,所以要将两组变量(学历和平均薪资)放入Excel表格中。首先选中两列数据,点击数据工具栏下的”数据分析“,在弹出的对话框中选择”回归“,点击”确定“。点击Y值输入区域(Y)后面的单元格选择,选择B列平均薪资, X值选择A列学历,勾选下方的线性拟合图。点击”确定“之后生成回归统计分析结果。主要包括SUMMARY OUTPUT、方差分析、RESIDUAL OUTPUT这三个部分。

January 15, 2019 · 1 min · jiezi

10 行代码提取复杂 Excel 数据

【摘要】 把 Excel 文件导入关系数据库是数据分析业务中经常要做的事情,但许多 Excel 文件的格式并不规整,需要事先将其中的数据结构化后再用 SQL 语句写入数据库。而一般情况下,结构化的工作量会比较大,而且很难通用,每次都要针对文件格式进行分析后再进行开发。 集算器的 SPL 语言是一款高效、灵活的工具,它能够轻松读取 excel 数据,然后结构化成“序表”后导入数据库。使用 SPL 语言后,以往需要编写数千行代码才能完成的 Excel 数据结构化入库工作,现在只需要不到 10 行代码就可以胜任,简单情况下甚至只需要 2、3 行代码!真的这么神奇吗?让我们去乾学院看看这些高招吧:10 行代码提取复杂 Excel 数据10行代码提取复杂Excel数据 下面我们将分情况讨论如何利用集算器将Excel数据进行结构化。文中用到的函数请参看集算器文档《函数参考》。1. 普通行式 先看最简单的情况:如下图所示,Excel文件中第一行是列标题,从第二行开始,每行是一条数据记录。 集算器处理这种文件也非常简单:A1 打开“学生成绩表.xlsx”文件并导入成序表,选项@t表示文件第一行是列标题A2 连接demo数据库A3 将A1中的序表存入到demo数据库的xscj表中,由于表中的列名和序表中的字段名一样,所以只需指定数据表名即可。update函数的更详细用法请查阅函数文档。A1中得到的序表如下图所示:A2、A3两步连接数据库和将序表存入数据库的方法是通用的,所以后面的例子中将不再写这两步,只关注于如何把Excel中的数据结构化成序表。2. 多行表头行式 大多数时候,Excel文件都不会象上例那么简单,表头往往比较复杂,有表名、项目名、页码、填表人、填写日期等等。比如这个样子: 对于这种表,我们在读取时就要跳过表头,直接从数据行开始读。A1 打开文件并导入数据成序表,参数“1,5”表示读第一个 sheet,从第 5 行开始读,一直读到文件结尾A2 将 A1 中读到的序表列名依次改为“序号、项目编码、项目名称、计量单位、数量、单价、合价”,即要存入的数据表的列名。运行后 A2 中的序表如下:3. 自由格式 有时Excel文件的数据并不是网格式的规则表,而是字段名后紧跟着字段值的自由格式,如下图的雇员信息表:每个雇员信息占据9行,依次往下排列。对这种文件,该怎么结构化呢?请看:A1 创建列名为“雇员 ID, 姓名, 性别, 职位, 生日, 电话, 地址, 邮编”的空序表A2 打开 Excel 数据文件A3 定义雇员信息所在单元格列号序列B3 定义雇员信息所在单元格行号序列A4 用 for 循环读取每个雇员信息B4 A3.(~/B3(#))先算出当前雇员单元格编号序列, 再读出这些单元格值组成雇员信息序列。第一次循环时为 [C1,C2,F2,C3,C4,D5,C7,C8],第二次循环时为[C10,C11,F11,C12,C13,D14,C16,C17]……每次行号加 9。$[A2.xlscell(] 与 “A2.xlscell(” 相同,都是表示一个字符串,它的好处是在 IDE 中编写程序时,如果 A2 单元格的编号发生了变化,$[A2.xlscell(]中的 A2 会自动变化,比如在 A2 前插入了一行,这个表达式就会变成 $[A3.xlscell(],而用引号的话,就不会自动变了。B5 判断雇员 ID 值是否为空,为空则退出循环,结束运行B6 将一条雇员信息存入 A1 序表尾B7 让雇员信息的行号序列都加上 9,读取下一条雇员信息运行后得到的 A1 序表如下:4. 交叉表Excel中还有交叉表格式的数据,如下图:数据结构化程序如下:A1 打开文件并导入数据成序表,参数“1,2”表示读第一个 sheet,从第 2 行开始读,一直读到文件结尾。选项 @t 表示开始行是列标题。A2 由于第二行第一个单元格是图片,读的数据为 null,第一列没有列标题,所以将第一列列名改为运货商。A3 以运货商为分组,对序表数据进行行列转换,选项 @r 表示将列数据转换为行数据,转换后新的列名分别为“货主地区”、“订单数量”。运行后得到的 A3 序表如下:5. 主子表在下图所示的员工信息登记表中,除了有员工本人的信息外,还有他的家庭成员信息。每个 sheet 保存一个员工的相关信息,所以有多少员工,就有多少个 sheet。对这种主子表结构的数据,需要创建两个序表分别保存主表和子表的数据,集算器程序如下:A1 创建列名为“身份证号, 姓名, 性别, 出生日期, 民族, 手机号, 部门, 家庭地址, 婚姻状况, 入职时间”的空序表,用于保存主表员工信息A2 创建列名为“身份证号, 姓名, 关系, 工作单位, 联系电话”的空序表,用于保存子表员工家庭成员信息A3 定义主表员工信息所在单元格序列A4 打开 Excel 数据文件A5 循环读取 Excel 文件各 sheet 数据B6 读取员工信息序列C6 将 B6 读取的员工信息保存到序表 A1B7 从第 6 行开始读取员工家庭成员信息,只读指定的“家庭成员, 姓名, 关系, 工作单位, 联系电话”5 列B8 将 B7 序表的家庭成员列改名为身份证号C8 为 B8 序表的身份证号列赋值为员工信息中的身份证号B9 将 B8 中的员工家庭成员信息保存到序表 A2程序运行后,序表 A1 如下图所示:序表 A2 如下图所示: 上面这些情况基本罗列了常见的 Excel 数据格式,如果遇到更复杂的文件,也可以灵活使用例子中的技巧予以应对。简单总结一下,集算器提供了非常灵活的在 excel 文件中定位和读取数据的功能,既可以成片读取网格数据,也可以精确定位单元格进行读取。再结合特有的“序表”对象,以往需要编写数千行代码才能完成的 Excel 数据结构化入库工作,现在只需要不到 10 行代码就可以胜任,简单情况下甚至只需要 2、3 行代码! ...

January 14, 2019 · 1 min · jiezi

用PHP读取Excel、CSV文件

PHP读取excel、csv文件的库有很多,但用的比较多的有: PHPOffice/PHPExcel、PHPOffice/PhpSpreadsheet,现在PHPExcel已经不再维护了,最新的一次提交还是在2017年12月25号,建议直接使用PhpSpreadsheet,而且这两个项目都是同一个组织维护的,本文介绍PhpSpreadsheet的使用。介绍PhpSpreadsheetPhpSpreadsheet这个库是纯PHP写的,提供了非常丰富的类和方法,而且支持很多文件格式:环境要求PHP >= 5.6开启php_zip扩展开启php_xml扩展开启php_gd2扩展开始使用????我们写一个简单的demo,来学习PhpSpreadsheet的使用,大概就是一个简单的文件上传页面,上传我们要读取的Excel文件,PHP接收到文件,调用PhpSpreadsheet读取Excel里面的内容。0. 配置环境略…,自己配置我当前的PHP版本是7.2.131. 新建一个项目mkdir democd demo2. 安装使用composer安装:composer require phpoffice/phpspreadsheet默认安装的是最新的稳定版本(1.5),如果想要安装dev版本,可以执行下面的命令:composer require phpoffice/phpspreadsheet:develop上面步骤执行完毕后,目录结构是这样的:3. 新建一个简单的html文件,用来上传Excel文件vim index.htmlindex.html里面的内容很简单,如下:这里要注意下:form表单的enctype一定要是multipart/form-data这只是一个简单的demo,一个form表单就可以了,运行后就是下面这样了 :)4. PhpSpreadsheet如何使用?在处理前端传过来的Excel文件之前,先来介绍下PhpSpredsheet如何使用。4.1 读取文件PhpSpreadsheet中读取文件有很多种,对于不同格式的文件有不同的读取方法,比如:xlsx格式,使用\PhpOffice\PhpSpreadsheet\Reader\Xlsx(),csv格式,使用\PhpOffice\PhpSpreadsheet\Reader\Csv(),乍一看这么多类就感觉有点复杂,其实这些类都实现了\PhpOffice\PhpSpreadsheet\Reader\IReader和\PhpOffice\PhpSpreadsheet\Writer\IWriter接口,指定了要加载的文件类型。我们可以直接使用\PhpOffice\PhpSpreadsheet\IOFactory这个工厂类:$spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load(‘demo.xlsx’);如果想在读写文件的时候设置一些属性,比如读写属性,可以这样设置:$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReaderForFile(“demo.xlsx”);$reader->setReadDataOnly(true);$reader->load(“demo.xlsx”);使用这个工厂类的好处就是你不需要关心文件上传的格式,它能自动帮识别,其实这个工厂类就是对你上传的文件做一些识别,如果识别出来是xls格式,就返回xls的reader,如果是csv,就返回csv的reader,通过分析代码我们可以看到这个IOFactory可以生产出如下的reader和writer:abstract class IOFactory{ private static $readers = [ ‘Xlsx’ => Reader\Xlsx::class, ‘Xls’ => Reader\Xls::class, ‘Xml’ => Reader\Xml::class, ‘Ods’ => Reader\Ods::class, ‘Slk’ => Reader\Slk::class, ‘Gnumeric’ => Reader\Gnumeric::class, ‘Html’ => Reader\Html::class, ‘Csv’ => Reader\Csv::class, ]; private static $writers = [ ‘Xls’ => Writer\Xls::class, ‘Xlsx’ => Writer\Xlsx::class, ‘Ods’ => Writer\Ods::class, ‘Csv’ => Writer\Csv::class, ‘Html’ => Writer\Html::class, ‘Tcpdf’ => Writer\Pdf\Tcpdf::class, ‘Dompdf’ => Writer\Pdf\Dompdf::class, ‘Mpdf’ => Writer\Pdf\Mpdf::class, ];…可以看到支持的类型还是蛮多的,但是很多都不常用。在IOFactory工厂中还可以指定读写的文件类型,返回对应的reader,这样就免去了识别文件类型的步骤,如下:$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader(“Xlsx”); // 指定为xlsx格式$spreadsheet = $reader->load(“demo.xlsx”);4.2 从源码比较两种读写方式首先,来看下IOFactory这个工厂类,我们在不指定reader类型时直接load,代码内部是要做一个识别格式的操作:// 源码解析// 不指定reader,直接获取上传的文件创建$reader = \PhpOffice\PhpSpreadsheet\IOFactory::load($_FILES[‘file’][’tmp_name’]);// IOFactory::load()public static function load($pFilename){ // 这步棋室就是创建reader,免去了你手动创建 $reader = self::createReaderForFile($pFilename); return $reader->load($pFilename);}// IOFactory::createReaderForFile()// 这步就是返回一个reader,具体返回什么reader,是根据文件名来的public static function createReaderForFile($filename){ // 判断文件是否存在并且可读,会抛出InvalidArgumentException File::assertFile($filename); // 根据文件后缀猜测类型 $guessedReader = self::getReaderTypeFromExtension($filename); if ($guessedReader !== null) { $reader = self::createReader($guessedReader); // Let’s see if we are lucky if (isset($reader) && $reader->canRead($filename)) { return $reader; } } // 如果没有检测到类型,就会遍历默认的reader数组,直到找到可以使用的那个reader foreach (self::$readers as $type => $class) { if ($type !== $guessedReader) { $reader = self::createReader($type); if ($reader->canRead($filename)) { return $reader; } } } throw new Reader\Exception(‘Unable to identify a reader for this file’);}从上面的代码,可以看到在load前是做了文件检测和类型判断的操作,然后再返回对应的reader,接下来,再来看看当我们指定了类型后,做了哪些操作的:// 指定reader$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();$spreadsheet = $reader->load($_FILES[‘file’][’tmp_name’]);上面的就比较简单了,直接创建reader,然后就load了,只是做了一些实例化的操作。这两种方法相比,第二种方法性能更好一点,当然前提是要知道文件格式。5. 读取Excel文件内容让我们接着继续上面的index.html,我们需要编写一个PHP文件来处理请求:require ‘vendor/autoload.php’;$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();try { $spreadsheet = $reader->load($_FILES[‘file’][’tmp_name’]);} catch (\PhpOffice\PhpSpreadsheet\Reader\Exception $e) { die($e->getMessage());}$sheet = $spreadsheet->getActiveSheet();$res = array();foreach ($sheet->getRowIterator(2) as $row) { $tmp = array(); foreach ($row->getCellIterator() as $cell) { $tmp[] = $cell->getFormattedValue(); } $res[$row->getRowIndex()] = $tmp;}echo json_encode($res);我们先引入autoload,接着创建了一个Xlsx的reader,然后load我们上传的文件,因为在excel中,内容都是按sheet区分的,每一个sheet中都由行和列组成,我们获取到当前使用的sheet,通过sheet获取到行的迭代对象,再针对每一行得到每一列对象,在PhpSpreadsheet中,cell是一个最小的单元,对应着第几行第几列,数据都是存在cell中,得到cell对象我们就能获取到数据。当我们上传如下内容后:返回结果如下:因为我们在读取时,是从第二行开始的,所以第一行的内容就不显示了。这里说一下,在Excel中第三列是一个时间,PhpSpreadsheet对时间的处理有点特殊。在PhpSpreadsheet中date和time在存储时都是作为数字类型,当要区分数字是时间格式时,需要用到format mask,默认情况下,format mask是开启了的,但如果设置setReadDataOnly等于true的话,就不能使用format mask,从而就区分不了数字和时间格式,PhpSpreatsheet将会全部作为数字处理。此时,我们开启只读模式看一下,$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();$reader->setReadDataOnly(true);输出结果如下:第三列就变成了奇怪的数字,当初这个问题还困扰了我半天。5. PhpSpreadsheet读取文件时的一些常用方法如果一个Excel中有多个sheet,只想操作其中的某几个sheet,可以设置setLoadSheetsOnly$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();// 参数支持字符串或一个数组$reader->setLoadSheetsOnly([‘sheet1’,‘sheet3’]);读取指定行和列的数据class MyReadFilter implements \PhpOffice\PhpSpreadsheet\Reader\IReadFilter{ public function readCell($column, $row, $worksheetName = ‘’) { // 只读取A1:E7的数据 if ($row >= 1 && $row <= 7) { if (in_array($column,range(‘A’,‘E’))) { return true; } } return false; }}$myFilter = new MyReadFilter();$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();$reader->setReadFilter($filterSubset);$spreadsheet = $reader->load(‘demo.xlsx’);上面的例子不够通用,可以修改下使之更为通用:class MyReadFilter implements \PhpOffice\PhpSpreadsheet\Reader\IReadFilter{ private $startRow = 0; private $endRow = 0; private $columns = []; public function __construct($startRow, $endRow, $columns) { $this->startRow = $startRow; $this->endRow = $endRow; $this->columns = $columns; } public function readCell($column, $row, $worksheetName = ‘’) { if ($row >= $this->startRow && $row <= $this->endRow) { if (in_array($column,$this->columns)) { return true; } } return false; }}$myFilter = new MyReadFilter(9,15,[‘A’, ‘B’, ‘D’]);列出Excel中所有sheet的名字$reader->listWorksheetNames(‘demo.xlsx’);列出一个sheet的信息,包括多少列、多少行$reader->listWorksheetInfo(‘demo.xlsx’);PhpSpreadsheet的学习与使用就到这,真的很强大,几乎满足了日常的所有需求,是读取Excel、CSV文件的利器。 ...

January 1, 2019 · 2 min · jiezi

React+React-Route+Antd+Recharts+Excel(获取Excel数据,绘制Charts)

转眼间2018年就过去了,来到的2019新的一年,在这里,祝大家新年快乐。知乎个人博客GithubDemoRepo开发缘由:因为一个很重要的朋友需要绘制一些Charts,但是嫌弃手绘太慢,因此这次放假写了这个小东西当前进度:简单的Demo Charts展示,包括AreaChart, BarChart, ComposedChart, LineChart, PieChart测试文件:src/common/files/info.xlsx附上RechartsReact-Route先上两张照片吧1、版本2、创建项目因为公司使用的 react+antd+ts, 虽然antd前两天搞了个圣诞惊吓,但是毋庸置疑,这个组件库做的确实很好啊,我不怕被喷,辩证一分为二,不能因为别人犯一点的错误,就否认人家吧,废话不多说,还是讲本文的主题吧首先先安装create-react-appnpm i -g create-react-appcreate-react-app Charts –scripts-version=react-scripts-ts-antd然后安装react-route-dom和rechartsyarn add react-route-domornpm i react-route-dom –savenpm i recharts –save因为TS检查较为严格,所以,我对TS有一些我自己需要rules的配置tslint.js{ “extends”: [“tslint:recommended”, “tslint-react”, “tslint-config-prettier”], “linterOptions”: { “exclude”: [ “config//*.js”, “node_modules//.ts”, “coverage/lcov-report/.js” ] }, “rules”: { “no-string-throw”: true, “no-unused-expression”: false, “no-unused-variable”: false, “no-use-before-declare”: false, “no-duplicate-variable”: false, “curly”: true, “class-name”: true, “triple-equals”: [true, “allow-null-check”], “comment-format”: [false, “check-space”], “eofline”: true, “forin”: false, “indent”: [true, “spaces”, 2], “label-position”: true, “max-line-length”: [true, 150], “member-access”: false, “no-arg”: true, “no-bitwise”: false, “no-console”: [true, “debug”, “info”, “time”, “timeEnd”, “trace” ], “no-construct”: true, “no-debugger”: true, “no-empty”: false, “no-eval”: true, “no-inferrable-types”: true, “no-shadowed-variable”: false, “no-string-literal”: false, “no-switch-case-fall-through”: false, “no-trailing-whitespace”: true, “no-var-keyword”: false, “object-literal-sort-keys”: false, “one-line”: [true, “check-open-brace”, “check-catch”, “check-else” ], “radix”: false, “typedef-whitespace”: [true, { “call-signature”: “nospace”, “index-signature”: “nospace”, “parameter”: “nospace”, “property-declaration”: “nospace”, “variable-declaration”: “nospace” }], “variable-name”: [true, “ban-keywords”], “whitespace”: [true, “check-branch”, “check-decl”, “check-type”, “check-preblock” ], “ordered-imports”: false, “jsx-no-lambda”: false, “interface-name”: [true, “never-prefix”], “prefer-const”: false }}TS初试React-Route 4.x提供给我们使用的都是以组件形式存在的。我们使用的时候就像我们以前使用组件那样使用就行了,详见React-Route官方文档。菜单栏,我觉得日后可能还会增加其他的Charts,所以我将菜单通过配置文件来控制,增加复用性。SideMenu.tsximport React, { Component } from ‘react’;import { Link } from ‘react-router-dom’;import classnames from ‘classnames’;import moment from ‘moment’;import ‘./index.scss’;import { menus } from ‘./menus’;import { Layout, Menu, Icon } from ‘antd’;import Timer from ‘src/components/Timer/Timer’;const { Header, Footer, Sider, Content } = Layout;const { SubMenu } = Menu;interface SideMenuProps { children?: any;}export default class SideMenu extends Component<SideMenuProps, any> { public state = { collapsed: false, selectedKeys: [menus[0].key], }; public toggle = () => { this.setState({ collapsed: !this.state.collapsed }); }; render() { const { collapsed, selectedKeys, } = this.state return ( <Layout className=“side-menu”> <Sider trigger={null} collapsible={true} collapsed={collapsed}> <div className=“logo”> <img src={require(‘src/common/images/logo.png’)} /> <a href=“https://github.com/Rain120/charts" target="_blank”> <span className={classnames(“title”)}><Icon type=“github” /></span> </a> <a href=“https://www.zhihu.com/people/yan-yang-nian-hua-120/activities" target="_blank”> <span className={classnames(“title”)}><Icon type=“zhihu” /></span> </a> </div> <Menu theme=“dark” mode=“inline” defaultSelectedKeys={selectedKeys}> { menus && menus.map(menu => ( menu.children ? ( <SubMenu key={menu.key} title={<span><Icon type={menu.icon} /><span>{menu.text}</span></span>}> { menu.children.map(item => ( <Menu.Item key={item.key}> <Link to={item.path}>{item.text}</Link> </Menu.Item> )) } </SubMenu> ) : ( <Menu.Item key={menu.key}> <Link to={menu.path} style={{ overflow: ‘hidden’ }}><Icon type={menu.icon} />{menu.text}</Link> </Menu.Item> ) )) } </Menu> </Sider> <Layout className=“r-content”> <Header> <Icon className=“trigger” type={collapsed ? ‘menu-unfold’ : ‘menu-fold’} onClick={this.toggle} /> <Timer timerStyle=“timer” /> </Header> <Content style={{ margin: ‘1rem’, padding: ‘1rem’, background: ‘#fff’, minHeight: ‘25rem’, }}> {this.props.children} </Content> <Footer style={{ textAlign: ‘center’ }}> ©{moment().format(‘YYYY’)} Created by Rainy </Footer> </Layout> </Layout> ); }}Menu.ts/* * @Author: Rainy * @Github: https://github.com/Rain120 * @Date: 2018-12-30 15:43:12 * @LastEditTime: 2018-12-31 13:28:04 */export const menus = [ { key: ‘menu-0’, icon: ‘bar-chart’, text: ‘Charts Demo Show’, path: ‘/’, }, { key: ‘menu-1’, icon: ‘dashboard’, text: ‘ReCharts’, children: [ { key: ‘1’, text: ‘Charts Drawer’, path: ‘/charts/charts-drawer’ }, ] }] as any;获取Excel的数据是通过使用大佬的xlsx插件来实现的,详见XLSX官网。npm i xlsx -S因为这次项目没有后端,所以其实我们对Excel文件的解析是在upload之前完成的public beforeUpload = (file: any, fileList: any) => { var rABS = true; const f = fileList[0]; var reader = new FileReader(); reader.onload = (e: any) => { let data: any = e.target.result; if (!rABS) { data = new Uint8Array(data); } var workbook = XLSX.read(data, { type: rABS ? ‘binary’ : ‘array’ }); // more sheet workbook.SheetNames.map(item => { var worksheet = workbook.Sheets[item]; var jsonArr = XLSX.utils.sheet_to_json(worksheet, { header: 1 }); this.handleImpotedJson(jsonArr); }) }; if (rABS) { reader.readAsBinaryString(f); } else { reader.readAsArrayBuffer(f); } return false;}upload configconst props = { accept: ‘application/vnd.openxmlformats-officedocument.spreadsheetml.sheet’, name: ‘file’, headers: { authorization: ‘authorization-text’, }, multiple: false, action: ‘’, beforeUpload: (file, fileList) => this.beforeUpload(file, fileList), onChange(info) { const status = info.file.status; if (status !== ‘uploading’) { console.log(info.file, info.fileList); } if (status === ‘done’) { message.success(${info.file.name} file uploaded successfully.); } else if (status === ’error’) { message.error(${info.file.name} file upload failed.); } }, };Charts组件因为使用的Charts比较多,所以使用recharts提供的组件ResponsiveContainer为了使得这些Charts不够缩放的影响。但是当前做的这些Charts大部分都是相同的结构,所以相同的部分应该抽离出来。因为其他的Charts都差不多,这里我只说一下LineChartsimport React, { Component } from ‘react’;import WrapperCharts from ‘./WrapperCharts’;import ‘./index.scss’;import { Line, Legend, Tooltip, XAxis, YAxis, CartesianGrid, LineChart, Label,} from “recharts”;export const COLOR_LISTS = [’#8884d8’, ‘#cf6868’, ‘#3fb549’, ‘#a6d41f’, ‘#8ad4d8’, ‘#cfdd68’, ‘#354449’, ‘#a75d1f’];interface LineChartsProps { data?: any; names?: any;}export default class LineCharts extends Component<LineChartsProps, any> { render() { const { data, names } = this.props; return ( <WrapperCharts class_name=“line-charts”> <LineChart data={data}> <CartesianGrid /> { names && <XAxis dataKey={names[0].dataKey} name={names[0].name} /> } <YAxis /> <Tooltip /> <Legend /> { names && names.slice(1).map((item, index) => ( <Line type=“monotone” dataKey={item.dataKey} key={index} name={item.name} stroke={COLOR_LISTS[index]} /> )) } <Label /> </LineChart> </WrapperCharts> ) }}github page deploynpm i -g gh-pagespackage.json配置"predeploy": “yarn run build”,“deploy”: “gh-pages -d build"部署yarn run deploy引入图片以上就是这两天做的小东西,写的和讲的都很潦草,请看管轻喷。 ...

January 1, 2019 · 4 min · jiezi

一个php文件就可以把数据库的数据导出Excel表格

数据库内容太多,复制粘贴太麻烦?那就用代码实现把,把代码写好了,导出还不容易吗,访问即可导出。excel.php<?php error_reporting(E_ALL ^ E_DEPRECATED); $localhost = ‘数据库地址’; $dbname = ‘数据库名’; $dbuser = ‘数据库账号’; $dbpwd = ‘数据库密码’; $tbname = “需要导出的数据库表名”; ob_end_clean(); header(‘Content-type: text/html; charset=utf-8’); header(“Content-type:application/vnd.ms-excel;charset=UTF-8”); header(“Content-Disposition:filename=data.xls”);// 文件名自己改,默认data.xls $conn = mysql_connect($localhost,$dbuser,$dbpwd) or die(“连接数据库失败”); mysql_select_db($dbname, $conn); mysql_query(“set names ‘UTF-8’”); $result=mysql_query(“SELECT * FROM $tbname”); echo “<table>”; echo “<tr>”; echo “<th>A1单元格</th>”; echo “<th>B1单元格</th>”; echo “<th>C1单元格</th>”; echo “<th>D1单元格</th>”; echo “</tr>”; echo “</table>”; while($row=mysql_fetch_array($result)){ //下面data改成你自己数据库对应的字段 $data1 = $row[“data1”]; $data2 = $row[“data2”]; $data3 = $row[“data3”]; $data4 = $row[“data4”]; //输出字段的数据到单元格 //下面data改成你自己数据库对应的字段 echo “<table>”; echo “<tr>”; echo “<td>$data1</td>”; echo “<td>$data2</td>”; echo “<td>$data3</td>”; echo “<td>$data4</td>”; echo “</tr>”; echo “</table>”; }?>然后访问excel.php就可以弹出表格下载了。作者:TANKING网站:likeyunba.com微信:likeyunba520 ...

December 28, 2018 · 1 min · jiezi

如何解析你,Excel的Date呀

简单的背景介绍不久前,我们接了一个自己做前端后端产品的活,从此过上了可怜巴巴敲代码开开心心收获知识的日子呢。那是一个平平无奇的周一下午用户小姐姐在群里说,系统筛选工卡有效期不好使。(系统:不不不,不是我的锅我看了一下数据库,发现,我们原定的有效期格式是这样的整整齐齐。数据库中当时的数据是这样的甚至是这样的看到这种情况,我觉得肯定是输入的时候输的不太对(年轻…于是我决定从Excel下手小姐姐们的操作流程是先用我们的系统导出一份Excel,编辑之后再导入系统的,那只要我把这工卡一列的格式限制为日期,就一定可以统一格式的,嗯。我们项目使用了js-xlsx处理表格的导入导出,下面是导出Excel的伪代码:import * as XLSX from ‘xlsx’;const xlsxMineType = ‘application/vnd.openxmlformats-officedocument.spreadsheetml.sheet’const data = 数据.map((s: any) => ({ID: s.id,工卡有效期: s.card_expired,……}));const sheet = XLSX.utils.json_to_sheet(data);const wb = XLSX.utils.book_new();XLSX.utils.book_append_sheet(wb, sheet, ‘员工信息表’);const wbbuf = XLSX.write(wb, { type: ‘base64’});this.success({ name: “员工信息表.xlsx”, data: wbbuf, type:xlsxMineType });通过 json_to_sheet 可以拿到包含单元格信息的对象{ A2: { t: ’n’, v: 3776 }, B2: { t: ’s’, v: ‘2019-04-01’ }, A3: { t: ’n’, v: 3831 }, B3: { t: ’s’, v: ‘2019-04-01’ }, A1: { t: ’s’, v: ‘ID’ }, B1: { t: ’s’, v: ‘工卡有效期’ }, ‘!ref’: ‘A1:B3’ }对象中以单元格位置作为key,每个单元格的值(v)、类型(t)等等属性作为value。其中单元格的类型支持:b Boolean, n Number, e error, s String, d Date看起来Date类型十分符合上面的要求,就尝试了一下:const sheet = XLSX.utils.json_to_sheet(data);// 筛选出除表头的工卡列Object.keys(sheet).filter(item => /^B/.test(item) && item !== “B1”).forEach(key => { sheet[key].t = “d”;})然鹅,如果工卡有效期本来就为空,这时候导出,打开Excel会报错,并且空的位置会变成NaN翻阅了各种中英文文档、Issue,导出一百多个员工信息表之后,我发现Excel真的很奇妙,或许应该在js上来格式化导入的数据,而不是限制单元格的类型。如果不控制单元格类型的话,那么当管理员输入日期的时候,这个单元格可能是:文本、常规、日期、自定义类型,所以只要保证不管单元格是什么格式,程序都能拿到正确的数据就好了。当管理员使的工卡有效期的单元格类型是文本或者常规的时候,则比较简单,程序可以按预期解析出来一个相应的字符串,用moment解析一下,就可以获得想要的格式的数据了。那么当有效期单元格的类型是日期和自定义的时候,我们拿到的数据是像下图一样这也就是之前数据库中奇怪的数字的由来,这个数字的意义,其实是当前日期距离1900年1月0日的天数。还需要注意的是,Excel中有个bug:它以为1900年是闰年,所以我们拿到的天数都会多了一天,因为转换之前还需要先进行减一操作…item.工卡有效期 = new Date(1900, 0, expried - 1)这样之后就可以拿到正确的日期啦。咕叽。 ...

December 6, 2018 · 1 min · jiezi

前后端导出/下载excel方法

一、通过后端处理导出1.) 后端响应头设置前端若想下载一个根据查询参数生成的excel报表文件,需要后端设置请求内容的类型,具体设置如下: response.reset(); response.setContentType(“application/vnd.ms-excel;charset=utf-8”); // 表明是excel类型 //response.setContentType(“application/octet-stream”); // 或设成通用二进制流类型 response.setHeader(“Content-Disposition”, “attachment;filename=test.xls”)); // 将请求的内容存为一个名为test的文件2.) 前端相应的代码正常情况下,用以下两种方法均可:window.open(’/url/download?param=xxx’)window.location = ‘/url/download?param=xxx’ // 不加href,是因为有些浏览器有兼容问题但如果window.open是在一个ajax回调里执行,浏览器会被安全拦截,解决方案:$.ajax({ …. success: function() { var win = window.open() win.location = ‘/url/download?param=xxx’ }})或直接用window.location$.ajax({ …. success: function() { window.location = ‘/url/download?param=xxx’ }})二、前端直接将json数据处理成excel文件具体完整代码如下:<button onclick=‘tableToExcel()’>json导出xls文件</button><script> function tableToExcel() { var jsonData = [{ name: ‘路人甲’, phone: ‘123456’, email: ‘123@123456.com’ }, { name: ‘炮灰乙’, phone: ‘123456’, email: ‘123@123456.com’ }] //列标题 var table = ‘<tr><td>姓名</td><td>电话</td><td>邮箱</td></tr>’ //循环遍历,每行加入tr标签,每个单元格加td标签 jsonData.forEach(function(item) { table += ‘<tr>’; for (let key in item) { //增加t为了不让表格显示科学计数法或者其他格式 table += &lt;td&gt;${item[key] + 't'}&lt;/td&gt; } table += ‘</tr>’; }) //Worksheet名 var worksheet = ‘Sheet1’ //下载的表格模板数据 var template = &lt;html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"&gt; &lt;head&gt; &lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8"&gt; &lt;!--[if gte mso 9]&gt; &lt;xml&gt; &lt;x:ExcelWorkbook&gt; &lt;x:ExcelWorksheets&gt; &lt;x:ExcelWorksheet&gt; &lt;x:Name&gt;${worksheet}&lt;/x:Name&gt; &lt;x:WorksheetOptions&gt; &lt;x:DisplayGridlines/&gt; &lt;/x:WorksheetOptions&gt; &lt;/x:ExcelWorksheet&gt; &lt;/x:ExcelWorksheets&gt; &lt;/x:ExcelWorkbook&gt; &lt;/xml&gt; &lt;![endif]--&gt; &lt;/head&gt; &lt;body&gt; &lt;table&gt;${table}&lt;/table&gt; &lt;/body&gt; &lt;/html&gt; // 下载模板 window.location.href = ‘data:application/vnd.ms-excel;base64,’ + base64(template) } //输出base64编码 function base64(s) { return window.btoa(unescape(encodeURIComponent(s))) }</script> ...

September 1, 2018 · 1 min · jiezi