ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[已解决] 在有控件的文档中,正则如何精准锚定目标位置?

[复制链接]

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-8-26 20:27 | 显示全部楼层
本帖最后由 weiyingde 于 2024-8-26 21:35 编辑
lss001 发表于 2024-8-26 12:55
可能是版本不同,
word365版本段落不需要声明为对象,
也不需要Range对象

     测试的时候,还忽略了一个细节,发现上述代码运行时匹配的字符刚好少了4个:解析和两个空格。
删去s,刚好适配。
     细细思之,删之有理。
     因为之所以用 str = Replace(Replace(osr, Chr(7), ""), Chr(1), ""),就是删去word忽略的而正则却统计不可见字符,至于你所说的回车符,所不可见,却是word和正则都认可的有效字符,应该不在删掉之列。
     而正则在word本来就认可的目标范围内所匹配的目标,其firstindex 和length值,又不必删去。
     换言之,用Replace(Replace(osr, Chr(7), ""), Chr(1), "")之后,还影响正则的判断,只局限于r = wt.End - wt.Start,因为按钮实打实占据了位置,而且也是在word认可的前提下,有字符的,你可以用ThisDocument.Paragraphs(1).Range.Text,看一看,第一段的结尾,有一个小方框,那大概就是按钮在word中所认可的字符,而这个却是正则所不认可的,为了方便正则锚定,匹配目标你已经减去,那么。现在在回归到word下,即Set oRng = Ydoc.Range(m, m + n),只有m=firstindex+按钮“占位”长度,而文本长度只有 m + n。
     说那么多,在正则搜索的文档中如有表格和控件,总结两句话:
     (1)对于有表格的一句Replace(osr, Chr(7), ""),搞定一切,无后顾之忧。
     (2)对于有按钮在,只要按钮不在正则匹配的目标之中[如本例匹配目标在第六段之后(表格除外),而按钮在第一段],只考虑到按钮所占位置的长度。
     (3)在正则所匹配的目标,回到word中锚定其位置,只考虑到目标的起始位置(range.start),不顾虑其文本长度(length),因而其对应的文档位置是start=mt.firstindex+按钮占位符长度,end=start+length,所以正则所匹配的文本区域:oRng=Activedocument.range(mt.firstindex+"按钮占位符"长度,mt.firstindex+按钮占位符长度+mt.length),其中"按钮占位符"长度=X段最后一个词的结尾—X段最后一个词的开头。(X为控件所在段落,控件且位于该段末尾)。
    请大侠审察所言正误,也请大侠运行附件代码进行测试。
    谢谢你多次指教开悟,也为我们多次的交流而庆贺。
    继续实验多个按钮,且按钮在第一段的中间位置等等情况……

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-8-26 21:32 | 显示全部楼层
     再做实验,先用msgbox  wt.End - wt.Start,测试一个按钮所占未知的长度,测的结果是35,即r=35,再    将标题中的按钮复制一个粘贴在第一段的中间,将r改为70,然后再将其复制一个放置在开头,将r改为105,其它代码一律不变,实验结果,一切均在预料之中,正则匹配正确!!
    35到底是这个按钮还是别的按钮,将此按钮删去,插入其他的按钮试试,r变成了38,有变化……
     就同一个按钮,拉伸一下(拉长、拉高,改变按钮的大小)试试,r仍旧是38,看来这个38我理解为按钮的占位长度是不正确的……,这就是说同一个按钮无论插在何处,无论大小,始终是一个定值,换了另一个按钮又是一个定值……
     再试一下,换一个checkbox如何?r=33,按钮变形r值33不变,改变caption的字符,仍然不变33。调另一个仍然是33。
    换一个ComboBox试试,r=33,再做其他的尝试,仍旧33不变,换另一个ComboBox又是33,将.text添加10字符,无论怎么变还是33.
    经过上述的实验,插入的command按钮不同次插入的略有变化,其他都是33!!!!
    最后再试几次command,都是38。
    结论:插入的控件计算的字符33或38.
    问题:这个33或38是有什么决定的呢?
    ?????
     

TA的精华主题

TA的得分主题

发表于 2024-8-26 23:55 来自手机 | 显示全部楼层
weiyingde 发表于 2024-8-26 21:32
再做实验,先用msgbox  wt.End - wt.Start,测试一个按钮所占未知的长度,测的结果是35,即r=35,再   ...

各种控件占用位置一般都有固定值
这个值由什么组成复合文档应该可以查到

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-8-27 14:00 | 显示全部楼层
再做实验,发现把三个控件放在一块(紧挨着放在第一段的后面),可以不改代码,word居然把三个控件合并当做一个单词词处理,只不过将单个的35乘以3,由原来的35变成了105。
请看下例。
Sub 要求匹配解析捕获四个()
    Dim mt, mk, oRng As Range, n&, m&
    Dim str$, tt$, arr() As Range, x%
    Dim rg As Range, dic As Object, k&, ph As Paragraph
   
    Set Ydoc = ThisDocument
    Set dic = CreateObject("Scripting.Dictionary")
    osr = Ydoc.Content
    '************************
    Set ph = Ydoc.Paragraphs(1) '在word其他版本中,这两句可能书写不同。
    Set wt = ph.Range.Words(ph.Range.Words.Count - 1)
    r = wt.End - wt.Start '有控件的,用这句。若有把控件放在结尾,并测出该控件所占据的字符数。
    '譬如此文档中的几个控件经意义测试可测出r值为
    MsgBox r
    '*************************
    str = Replace(Replace(osr, Chr(7), ""), Chr(1), "")
    With CreateObject("vbscript.regexp")
        .Global = True
        .Ignorecase = False
        .MultiLine = True
        .Pattern = "(^解析\s*)([A-D].+?)([A-D].+?)([A-D].+?)$"              '捕获四项
        '.Pattern = "(^解析\s+)([A-D].+?)?([A-D].+?)?([A-D].+?)?([A-D].+?)?$ '效果同上
        '.Pattern = "(^解析\s*)([A-D].*?)([A-D].*?)([A-D].*?)$"              '捕获四项,与上同。
        '.Pattern = "(^解析\s*)([A-D].*?){3}$"                               '捕获两项
        '.Pattern = "(^解析[^\r]*)([A-D](?:(?![A-D\r]).)*){3}\r"             '捕获两项 子项:“解析”二字,“解析”的第三项,因[A-D]属于解析部分的小项,属于第三级别,不可在第二级别捕获到。
        '.Pattern = "(^解析[^\r]*)(([A-D](?:(?![A-D\r]).)*){3})\r"           '捕获两项 “解析”二字,整个"解析"内容。
        For Each mt In .Execute(str)
            m = mt.FirstIndex + r: n = mt.Length                           '
            Set oRng = Ydoc.Range(m, m + n)
            MsgBox oRng
        Next
    End With
End Sub

三个按钮合并为一.rar

34.87 KB, 下载次数: 7

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-8-27 14:29 | 显示全部楼层
本帖最后由 weiyingde 于 2024-8-27 14:56 编辑

七个按钮集中置于第一段段后,程序自动能算出七个的所占字符数,运行正常,锚定精准。

附件如下。

七个按钮合并为一 .rar

41.39 KB, 下载次数: 8

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-8-27 14:51 | 显示全部楼层
本帖最后由 weiyingde 于 2024-8-27 15:02 编辑

七个分作两边,程序不能自己测定长度,只好先放在一起测出长度,然后再赋一个定值。正常运行,精准定位。如,此例中r=240.
唯一的遗憾是,程序不能自动测出七个的总长,必须事先测定,赋一个定值。

请问:大侠,有优化代码,程序自我搞定的吗?愿受到指教,盼得到援手。
附件如下:

七个安放两边 .rar

40.94 KB, 下载次数: 10

TA的精华主题

TA的得分主题

发表于 2024-8-27 14:56 来自手机 | 显示全部楼层
weiyingde 发表于 2024-8-27 14:51
七个分作两边,程序不能自己测定长度,只好先放在一起测出长度,然后再赋一个定值。正常运行,精准定位。如 ...

下载测试了一下,确定可行
现在考虑如果是控件在文档中间怎么处理
现在想到的是把InlineShape替换为Shape
不知您有什么处理方法

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-8-27 15:03 | 显示全部楼层
lss001 发表于 2024-8-27 14:56
下载测试了一下,确定可行
现在考虑如果是控件在文档中间怎么处理
现在想到的是把InlineShape替换为Sha ...

我想不必,只要绕个这个难关,后续的好办。

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-8-27 15:07 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
本帖最后由 weiyingde 于 2024-8-27 15:13 编辑
lss001 发表于 2024-8-27 14:56
下载测试了一下,确定可行
现在考虑如果是控件在文档中间怎么处理
现在想到的是把InlineShape替换为Sha ...

我试了一试,这个没办法,而且这种做法很奇葩,不合实际,就不考虑了。
我们只考虑日常工作中适用、够用的东西。

TA的精华主题

TA的得分主题

发表于 2024-8-28 09:51 来自手机 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
本帖最后由 lss001 于 2024-8-28 10:28 编辑
weiyingde 发表于 2024-8-27 14:51
七个分作两边,程序不能自己测定长度,只好先放在一起测出长度,然后再赋一个定值。正常运行,精准定位。如 ...


把星号这段代码改一下即可

    '************************
    str = Replace(osr, Chr(1), "") '控件替换
    Set ph = Ydoc.Paragraphs(1)
    Set wt = ph.Range.Words(ph.Range.Words.Count)
    'r等于第一段落总长度-段落文本长度+控件个数
    r = wt.End - Len(ph.Range.Text) + (Len(osr) -len(str))
    MsgBox r
    '*************************
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

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

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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