ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
楼主: ggmmlol

[原创] 表达式求值自定义函数突破255字符限制并兼容64位office

  [复制链接]

TA的精华主题

TA的得分主题

 楼主| 发表于 2019-10-23 09:22 | 显示全部楼层
本帖已被收录到知识树中,索引项:自定义函数开发
本帖最后由 ggmmlol 于 2019-10-26 21:37 编辑

本次更新,包含2个方面:1、提高效率;2、对0层括号的超长计算式,优化计算过程为分段处理。理论上可计算无限长度的无括号的四则运算式。

为提高函数运算效率,再次使用模块级全局变量,减少创建Html对象的次数,为修正“当不规范的计算式造成的‘运行错误’时,自动引用上一次函数结果的Bug”,设置模块内全局变量,比较与上一次结果的异同,如果相同,则强制上一次的结果为"空",然后再次计算,如果计算结果仍为空,判定为计算式不规范。此外,为减少DDL缓存,每2^10次函数计算后,清除原对象,重建html对象。

代码多了不少,但为了效率提升,还是很值得的。
jss.rar (42.9 KB, 下载次数: 131)

  1. Option Explicit
  2.     Private oDom As Object, oWin As Object, JSCode As String, Initialized As Boolean, beCleaned As Boolean, Partitioned As Boolean
  3.     Private tms%, oReg As Object, lastValue, lastexp$, a, b

  4. Sub Form_Load()
  5.     Dim i%, tmp0$, tmp1$
  6.     JSCode = "<script Language = JScript> function JS_EVAL(){return ExpValue}; var ExpValue; </script>"
  7.     Set oDom = CreateObject("htmlfile")
  8.     Set oWin = oDom.parentWindow
  9.     oDom.write JSCode
  10.     Set oReg = CreateObject("vbscript.regexp")
  11.     oReg.Global = True
  12.     tmp0 = "\blog\(、\blog10e\b、\bln(?=10\b|2\b)、+、-、×、÷、(、)、(\d*\.?\d+|\w*\([^\(\)]*\)|\w+)\^(-?\d*\.?\d+|\w*\([^\(\)]*\)|\w+)、" & _
  13.             "\btrunc\b、\bint\b、\b(sqrt|round|random|pow(er)?|pi(\(\))?|min|max|log(10e)?|ln(2|10)|exp|e|abs|a?tan2?|a?sin|a?cos)\b、" & _
  14.             "\[[^\[\]]*\]|【[^【】]*】|(Math\.)(?=\1)|[\f\n\r\v\t]、power\b、Math.e\b、\.pi(\(\))?、\b(Math\.)?ln\(、(-\+*-|\+)+(?=[\+\-])|[\+\-]+$、--"

  15.     tmp1 = "log10e*log(、Math.LOG10E、Math.LN、+、-、*、/、(、)、pow($1,$2)、" & _
  16.             "parseInt、Math.floor、Math.$1、、pow、Math.E、.PI、Math.log(、、+"
  17.     a = Split(tmp0, "、")
  18.     b = Split(tmp1, "、")
  19.     lastexp = Empty
  20.     Initialized = True
  21. End Sub

  22. Private Function EXPCLEAN(ByVal exp$) As String
  23.     Dim i As Integer
  24.     If Not Initialized Then Form_Load
  25.     If Not beCleaned Then
  26.         exp = LCase(exp)
  27.         With oReg
  28.             For i = 0 To UBound(a)
  29.                 .Pattern = a(i)
  30.                 exp = .Replace(exp, b(i))
  31.             Next
  32.         End With
  33.         beCleaned = True
  34.     End If
  35.     EXPCLEAN = exp
  36. End Function

  37. Function JSEVAL(ByVal s$) As Variant
  38. Dim s1$, s2$, s3$
  39.     s = EXPCLEAN(s)
  40.     If Len(s) = 0 Then
  41.         JSEVAL = ""
  42.     Else
  43.         If s = lastexp And Len(lastValue) Then JSEVAL = lastexp: Exit Function
  44.         If tms >= 1023 Then ReSet
  45.         If Not Partitioned Then
  46.             oReg.Pattern = "^([\d\D]*?)(\b\w[^()]{2040,}\w\b(?!\.))[\d\D]*"
  47.             If oReg.test(s) Then
  48.                 Partitioned = True
  49.                 oReg.Pattern = "^([\d\D]*?)(\b\w[^()]{60,2044}\w\b(?!\.))[\d\D]*"
  50.                 Do While oReg.test(s)
  51.                     s1 = oReg.Replace(s, "$1")
  52.                     s2 = oReg.Replace(s, "$2")
  53.                     s3 = Mid(s, Len(s1) + Len(s2) + 1)
  54.                     s2 = JSEVAL(oReg.Replace(s, "$2"))
  55.                     s = s1 & s2 & s3
  56.                 Loop
  57.                 Partitioned = False
  58.             End If
  59.         End If
  60.         oDom.write "<script Language = JScript> ExpValue = " & s & "; </script>"
  61.         JSEVAL = oWin.eval("JS_EVAL()")

  62.         If JSEVAL = lastValue And IsNumeric(lastValue) Then
  63.             oDom.write "<script Language = JScript> ExpValue = """"; </script>"
  64.             JSEVAL = oWin.eval("JS_EVAL()")
  65.             oDom.write "<script Language = JScript> ExpValue = " & s & "; </script>"
  66.             JSEVAL = oWin.eval("JS_EVAL()")
  67.         End If
  68.         If Len(JSEVAL) = 0 Then JSEVAL = VBA.Error$(93)
  69.     End If
  70.     lastValue = JSEVAL: lastexp = s: beCleaned = Partitioned: tms = tms + 1
  71. End Function

  72. Sub ReSet()
  73.     Set oWin = Nothing
  74.     Set oDom = Nothing
  75.     Initialized = False
  76.     beCleaned = False
  77.     Partitioned = False
  78.     lastexp = Empty
  79.     lastValue = 0
  80.     tms = 0
  81.     Form_Load
  82. End Sub
复制代码




TA的精华主题

TA的得分主题

发表于 2019-12-10 10:05 | 显示全部楼层
大神,好象还是有点问题,当出现非标计算式后每次按F9重算结果经常不一至

第一次是这样

第一次是这样

按F9后为这样

按F9后为这样

再按F9又变

再按F9又变

TA的精华主题

TA的得分主题

发表于 2019-12-22 10:55 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
大神,出现这种类型的错误计算式会弹出下图
QQ图片20191222105411.png

TA的精华主题

TA的得分主题

 楼主| 发表于 2020-1-13 12:15 | 显示全部楼层
lu6200 发表于 2018-12-23 00:54
楼主,能不能添加注释使用不区分中英文中括号,纯汉字不用添加括号的代码呢    非常感谢,这个对于外出或者 ...

我新发表了一个对工程量计算式求值的加载宏小工具,可以对任意格式的工作簿中的计算式进行快速计算(可“自动实时”或“手动批量”计算),并设置计算式中注释字符的字体格式。
且:
1、支持包含“代号”(以下划线接一个“汉、英”字符开始,后续可以接任意多个“汉、英、数”字符,如:_代号1_DH1_D栋3层C轴
2、支持两种注释字符:a)“格式化”的注释字符,即成对方括号包含的任意字符,b)既不在成对方括号之中,又不能构成计算式有效字符(代号、函数名称、数值、运算符等)的任意字符。这种称为“灵活式”的注释字符。
3、支持全角的括号、花括号;全角的四则运算符;特殊常量圆周率的代号字符“π
4、支持全部Excel工作表函数。
5、源码全公开,可以放心使用。也可供VBA自学人员参考。

TA的精华主题

TA的得分主题

发表于 2020-6-14 23:25 | 显示全部楼层
image.png

这种函数的计算过程,好像没有办法计算

TA的精华主题

TA的得分主题

发表于 2020-6-15 13:03 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2020-6-18 15:11 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
ggmmlol 发表于 2020-1-13 12:15
我新发表了一个对工程量计算式求值的加载宏小工具,可以对任意格式的工作簿中的计算式进行快速计算(可“ ...

能不能帮忙看看45楼的情况,如何解决呢,谢谢

TA的精华主题

TA的得分主题

 楼主| 发表于 2020-6-18 17:35 | 显示全部楼层
tangteng822 发表于 2020-6-18 15:11
能不能帮忙看看45楼的情况,如何解决呢,谢谢

就给个图片看?

TA的精华主题

TA的得分主题

发表于 2020-6-18 20:56 | 显示全部楼层
喔喔,不好意思,忘记了,嘿嘿。先开工程量这个文件,再开jss。谢谢

EVALUATE.zip

47.22 KB, 下载次数: 52

公式

TA的精华主题

TA的得分主题

 楼主| 发表于 2020-6-19 10:54 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
tangteng822 发表于 2020-6-18 20:56
喔喔,不好意思,忘记了,嘿嘿。先开工程量这个文件,再开jss。谢谢

看了,头回见这种工程量计算式,抱歉,爱莫能助,因为这个自定义函数只能支持数学三角函数,也就是常见科学计算器上所提供的函数,并不是任意函数都可以处理的。
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-11-16 21:26 , Processed in 0.047298 second(s), 8 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表