在上一节中,实现了WPS报表查询相关的代码,但是与function CommandButton1_Click()这个函数内容相比,function CommandButton2_Click()这个函数内代码较多,需要对其内容适当精简,将部分功能使用函数替代。
? 首先优化function CommandButton1_Click()的代码:
在 第2节 中提到:“JSA 宏编辑器看不到工作表(Worksheet)对象,Worksheet对象属性CodeName是空值,无法在代码中使用这个属性引用对象。”
所以将"报表"、"字典"这些字符串使用函数替换。如果日后修改工作表,可以直接修改常量定义部分,避免了全文替换再次调试代码等情况。
//查询按钮的单击事件function CommandButton1_Click(){ /* 使用getReprotShName() 替换"报表"这个字符串 以应对日后工作表可能改名的情况 getReprotName() 放在lib模块 */ let ReportSh = Application.Worksheets.Item(getReportShName()) 电脑 //使用getDictShName() 替换"字典"这个字符串 let DictSh = Application.Worksheets.Item(getDictShName()) let ReportQuery = ReportSh.QueryTables.Item(1) ReportQuery.CommandText = DictSh.Range("D1").Value2.replace(/\?/g, getWhereStr(ReportSh)) ReportQuery.Refresh()}
在lib模块,实现常量定义:
/* 定义常量 */function getReportShName(){ return "报表"}function getDictShName(){ return "字典"}function getProjectShName(){ return "项目分类明细汇总"}function getDisbursedShName(){ return "支出明细"}
? 优化function CommandButton2_Click()的代码,有注释的即为优化部分:
function CommandButton2_Click(){//使用按钮功能时,当前活动工作表必定是报表let ShReport = Application.ThisWorkbook.ActiveSheetlet DataRange = ShReport.QueryTables.Item(1).ResultRangelet r1 = getQuotaRange(DataRange)let r2 = getDisbursedRange(DataRange)let c1 = Selection.Cells(1) 电脑 if (!Intersect(c1, Union(r1, r2))) {alert(HintMsg(1))return 0} let UnitValue = ShReport.Range("f1").Text //将 BoolUnit 改为 isUnit 更好let isUnit = UnitValue == "0-全部" || UnitValue == "" /* 将 isUnit 和 OrderValue 作为参数传入lib模块的 getOrderWhere(IsUnit, OrderValue) 获取根据报表排序设定的条件 let OrderValue = ShReport.Cells.Item(c1.Row, 2).Value2 */let AddWhere = getOrderWhere(isUnit, ShReport.Cells.Item(c1.Row, 2).Value2) /* 将 TitleValue 作为参数传入lib模块的 getTitleWhere(TitleValue) 获取根据报表标题设定的条件 let TitleValue = ShReport.Cells.Item(4, c1.Column).Value2 */// 定义在where里追加的第二个条件let AddWhere2 = getTitleWhere(ShReport.Cells.Item(4, c1.Column).Value2)// 使用 getDictShName() 替换"字典"这个字符串let ShDict = Application.Worksheets.Item(getDictShName()) let whereStr = getWhereStr(ShReport)let sqlstr = ShDict.Range("d3").Value2.replace(/\?/g, whereStr +电脑 AddWhere + AddWhere2)let cnstr = Application.ThisWorkbook.Connections.Item(1).OLEDBConnection.Connection // 使用 getDisbursedShName 替换"支出明细"这个字符串let ShDetail = Application.Worksheets.Item(getDisbursedShName())for (let qt of ShDetail.QueryTables){qt.ResultRange.Clear()qt.Delete()}let qDetail = ShDetail.QueryTables.Add(cnstr, ShDetail.Range("A3"), sqlstr)qDetail.Refresh() //使用 getProjectShName 替换"支出明细"这个字符串let ShProjectDetails = Application.Worksheets.Item(getProjectShName())sqlstr = ShDict.Range("d2").Value2.replace(/\?/g, whereStr + AddWhere + AddWhere2)for (let qt of ShProjectDetails.QueryTables){qt.ResultRange.Clear()qt.Delete()}let qProjectDetails = ShProjectDetails.QueryTables.Add(cnstr, ShProjectDetails.Range("A3"), sqlstr)qProjectDetails.Refresh()//集中管理使用消息类字符串alert(HintMsg(2))}
lib模块相关代码:
/*返回提示性消息 *///集中管理使用消息类字符串function HintMsg(n){switch(n){case 1:return "所选单元格不在金额汇总数据显示区域,无法显示明细数据,请重新选择。"case 2:return "明细查询完成,请切换到【支出明细】和【项目分类明细汇总】工作表(Sheet)查看。"case 3: return "未知的排序值:"default: return "未定义错误消息"}}/* 函数名: getOrderWhere(IsUnit, OrderValue) 获取根据报表排序设定的条件 *传入两个参数,IsUnit 是否是一个单位, OrderValue 为排序单元格的值 *返回值sql-where语句 */function getOrderWhere(IsUnit, OrderValue){//定义一个在sql where条件里增加的条件let AddWhere = ""/* 解析OrderValue,判断当前活动单元格位于什么汇总级别 */if (OrderValue == '0'){ } //汇总合计行,什么也不用做,全部提取就好了 else { //根据排序值的长度来判断是哪一级的汇总switch(OrderValue.length){case 7: //类款项的汇总行/* 查询的是 2010000 这种类汇总行 */if (OrderValue.substr(3,4) == "0000"){ // aSql示例:and (left([支出功能分类],3) = '201')AddWhere = " and (left([支出功能分类],3) = '" + OrderValue.substr(0,3) +"')" } /* 查询的是 2010100 这种款汇总行 */else if (OrderValue.substr(5,2) == "00") { // aSql示例:and (left([支出功能分类],5) = '20101')AddWhere = " and (left([支出功能分类],5) = '" + OrderValue.substr(0,5) +"')" } /* 查询的是 2010201 这种项汇总行 */else { // aSql示例:and (left([支出功能分类],7) = '2010101')AddWhere = " and (left([支出功能分类],7) = '" + OrderValue.substr(0,7) +"')" } breakcase 9://单位汇总行-缺款、项,只有类+单位的汇总行 201+101003// aSql示例:and (left([支出功能分类],4) = '201-') and (left([单位],6) = '101003') AddWhere = " and (left([支出功能分类],4) = '" + OrderValue.substr(0,3) +"-')" AddWhere += IsUnit ? " and (left([单位],6) = '" + OrderValue.substr(4) + "')" : ""breakcase 11://单位汇总行-缺项,只有类款+单位的汇总行 20102+101003// aSql示例:and (left([支出功能分类],6) = '20102-') and (left([单位],6) = '101003')AddWhere = " and (left([支出功能分类],6) = '" + OrderValue.substr(0,5) +"-')" AddWhere += IsUnit ? " and (left([单位],6) = '" + OrderValue.substr(6) + "')" : ""breakcase 13://单位汇总行 类款项+单位的汇总行 2010201+102001// aSql示例:and (left([支出功能分类],8) = '2010201-') and (left([单位],6) = '101003')AddWhere = " and (left([支出功能分类],8) = '" + OrderValue.substr(0,7) +"-')" AddWhere += IsUnit ? " and (left([单位],6) = '" + OrderValue.substr(8) + "')" : ""breakdefault:Console.log(HintMsg(3) + OrderValue)}}return AddWhere}/* 函数名: getTitleWhere(TitleValue) 获取根据报表标题设定的条件 *传入参数TitleValue为标题单元格的值 *返回值sql-where语句 */function getTitleWhere(TitleValue){//列举项目分类明细内容 如果标题是这里面的内容,要查询项目分类明细const ProjectDetails = "工资福利支出对个人和家庭补助支出公用经费部门预算项目专项资金项目其他项目"let AddWhere2 = ""//查询的是项目分类明细if (ProjectDetails.indexOf(TitleValue) > -1){AddWhere2 = TitleValue == "其他项目" ? " and ([项目类别] not in ('工资福利支出','对个人和家庭补助支出','公用经费','部门预算项目','专项资金项目')" : " and ([项目类别] ='" + TitleValue + "')"}return AddWhere2}
至此,相关代码优化基本完成,CommandButton2_Click()内的代码可读性大幅度提高,下一节,将完成报表格式化的相关代码,使报表更美观。