
本文于2023年6月26日首发于本人同名公众号:Excel活学活用,更多文章案例请搜索关注!
☆本期内容概要☆
代码调试
发票登记管理系统EXCEL版更新
大家好,我是冷水泡茶,前期我们分享了【发票登记管理系统EXCEL版】,还分享了OFD发票提取代码修改的方法【OFD发票提取代码修改方法】,本以为万事大吉了,然而架不住发票花式繁多,还是有不少OFD发票读取异常。当然,我们不能怪它种类多,只能怪自己孤陋寡闻了。
后来,想起上次文章中提到的,应该按节点的位置来提取数据:

但是,问题来了,节点的位置怎么拿到呢?难道真的要去扳手指头数吗?那也是万万不能干的。
我们在提取OFD发票的开票项目时,采用的是循环节点方式,我们可以在这里做点文章,用一条Debug.print命令把节点序号和文本输出到“立即窗口”查看:
If i < 100 Then Debug.Print i & " | | " & xmlNodeList.Item(i).TextEnd If
读取一张OFD发票,查看“立即窗口”:

我们可以看到节点的顺序代码及对应发票项目字段,这里加了个i<100的判断,原因是有张发票节点数量有300多个。开票项目有这么多:

如果有多张发票,这样一张一张地看效率非常之低,也容易看错,不容易找到规律,我想既然能输出到立即窗口,也应该能输出到EXCEL表,我把它们并列排列,这样应该能看得更清楚:
With temWS .Cells(1, lastCol + 1).Offset(i, 0).Value = Format(i, "00") & " | | " & xmlNodeList.Item(i).TextEnd With
temWS是一个WorkSheet变量:Set temWS = Sheets("TEM"),运行结果输出到工作表Sheets(“TEM"),是这样子的:

这样看起来就方便多了,有了这些信息,我们就可以改代码:
ElseIf Len(InvoiceType) = 20 Then InvoiceCode = Left(xmlNodeList.Item(0).Text, 12) InvoiceNo = Right(xmlNodeList.Item(0).Text, 8) invoiceDate = xmlNodeList.Item(1).Text BuyerName = xmlNodeList.Item(2).Text BuyerTaxID = xmlNodeList.Item(3).Text SellerName = xmlNodeList.Item(4).Text SellerTaxID = xmlNodeList.Item(5).Text totalAmount = xmlNodeList.Item(12).Text Amount = xmlNodeList.Item(7).Text TaxAmount = xmlNodeList.Item(9).TextEnd If
代码解析:这里根据发票类型InvoiceType来判断各个发票项目的位置
目前可知的发票类型有:建筑服务、货物运输服务、XX增值税电子普通发票、差额征税-差额开票、无发票类型的。上面的代码就属于“无发票类型”,第一个节点字段就是20位发票号码。发票类型在第一个节点(0节点),我们根据它的值来判断各发票项目的位置。
XX增值税电子普通发票,这种版式的发票是旧版的增值税普通发票,目前发现该类发票下面,至少有三种版式,目前采用判断日期字段的位置来确定其他项目的位置,方法是判断某一节点里是否包括“年”字。
金额、税额、价税合计,在各版式的发票中的排列也有不同,有的金额在前,有的的价税合计在前,这就是为什么我在按类型取数以后,通过定位“¥”符合来取得这三个数字,然后再排序,最大的是价税合计,金额次之,两者相减得税额。
'检查节点文本是否包含 "¥" 符号 If xmlNode.Text = ChrW(165) Then '获取¥符号后面的数字 ReDim Preserve Numbers(j) Numbers(j) = CDbl(nextNode.Text) j = j + 1 End If ......'数组降序排序 Call BubbleSort(Numbers, "desc") If IsNumeric(Amount) = False Or Amount = "" Then totalAmount = Numbers(0) Amount = Numbers(1) TaxAmount = totalAmount - Amount End If
但即便这样,也出现了问题,还记得前面提到的开票项目巨多的发票吗?它有两页,在第一页上没有价税合计,原来用“价税合计”-“金额”=“税额”的方法就行不通了,要改为直接取金额、税额:
Amount = xmlNodeList.Item(7).TextTaxAmount = xmlNodeList.Item(9).Text
基本上也就这些了,目前,OFD发票的读取方式全部改为按节点排列位置读取。也许这样也不是一个好办法,有谁有好的建议请留言。
完整ReadOFDInvoiceInfo过各代码我放在第二条,获取过示例文件的朋友,可以把代码复制替换原来代码。有问题请在文章下面留言探讨。
好,今天就到这吧。欢迎点赞、留言、分享,谢谢大家,我们下期再会。
☆往期合集☆【2023年3月】【2023年4月】【2023年5月】