ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[求助] VBA将选项对齐

[复制链接]

TA的精华主题

TA的得分主题

发表于 2024-3-4 22:05 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
本帖最后由 sylun 于 2024-3-4 22:40 编辑

可以试试如下代码,采用平分制表位定位:
  1. Sub test()
  2.     '试题选项对齐(最多6个选项),仅针对纯文本文档
  3.     Dim i%, j%, k%, fontsize%, colwidth!, maxlen%, tabwidth!
  4.     Dim qs, opt, olen
  5.     Dim Reg As Object, Matches As Object, Match As Object, aRange As Range
  6.    
  7.     Set Reg = CreateObject("vbscript.regexp")
  8.     With Reg
  9.         .Global = True
  10.         .MultiLine = True
  11.         .Pattern = "^\d+\.\s.+?([A-F].+?)\r+(【答案】[A-F]+\r+)*(?=(^\d+\.|$))"
  12.         Set Matches = .Execute(ActiveDocument.Content.Text)
  13.         ReDim qs(2, Matches.Count - 1)
  14.         For Each Match In Matches
  15.             With Match
  16.                 qs(0, i) = .firstindex + InStr(.Value, Chr(13))
  17.                 qs(1, i) = qs(0, i) + Len(.SubMatches(0))
  18.                 qs(2, i) = Trim(.SubMatches(0))
  19.                 i = i + 1
  20.             End With
  21.         Next
  22.         
  23.         With ActiveDocument.Range(qs(0, 0), qs(0, 0))
  24.             fontsize = .Font.Size
  25.             colwidth = .PageSetup.TextColumns(1).Width
  26.         End With
  27.         .Pattern = "(?:^|[\s ]+)([A-F])[\..]"
  28.         For i = i - 1 To 0 Step -1
  29.             qs(2, i) = Replace(qs(2, i), Chr(9), " ") '预防性替换
  30.             qs(2, i) = .Replace(qs(2, i), Chr(9) & "$1.")
  31.             qs(2, i) = Replace(qs(2, i), Chr(13), "")
  32.             qs(2, i) = Mid(qs(2, i), 2)
  33.             opt = Split(qs(2, i), Chr(9))
  34.             ReDim olen(UBound(opt))
  35.             For j = 0 To UBound(olen)
  36.                 olen(j) = Len(opt(j))
  37.             Next
  38.             maxlen = 0
  39.             For j = 0 To UBound(olen)
  40.                 If olen(j) > maxlen Then maxlen = olen(j)
  41.             Next
  42.             
  43.             Application.ScreenUpdating = False
  44.             Set aRange = ActiveDocument.Range(qs(0, i), qs(1, i))
  45.             With aRange
  46.                 With .ParagraphFormat  '根据字符数最多的选项设置制表位
  47.                     .TabStops.ClearAll
  48.                     Select Case fontsize * (maxlen - 2)
  49.                     Case Is > (colwidth - 2 * fontsize) / 2
  50.                         qs(2, i) = Replace(qs(2, i), Chr(9), Chr(13))
  51.                     Case Is > (colwidth - 2 * fontsize) / 4 Or j = 2
  52.                         .TabStops.Add (colwidth + 2 * fontsize) / 2
  53.                         If j > 2 Then qs(2, i) = Replace(qs(2, i), Chr(9) & "C.", Chr(13) & "C.")
  54.                         If j > 4 Then qs(2, i) = Replace(qs(2, i), Chr(9) & "E.", Chr(13) & "E.")
  55.                     Case Is < (colwidth - 2 * fontsize) / 3 And j <> 4
  56.                         .TabStops.Add (colwidth + 4 * fontsize) / 3
  57.                         .TabStops.Add 2 * (colwidth + fontsize) / 3
  58.                         If j > 3 Then qs(2, i) = Replace(qs(2, i), Chr(9) & "D.", Chr(13) & "D.")
  59.                     Case Else '暂不考虑一行可容纳五六个选项的情形
  60.                         .TabStops.Add 2 * fontsize + (colwidth - 2 * fontsize) / 4
  61.                         .TabStops.Add 2 * fontsize + (colwidth - 2 * fontsize) / 2
  62.                         .TabStops.Add 2 * fontsize + 3 * (colwidth - 2 * fontsize) / 4
  63.                     End Select
  64.                 End With
  65.                 .Text = qs(2, i)
  66.                 .End = .End + 1
  67.                
  68.                 k = (UBound(olen) + 1) / .ComputeStatistics(4)
  69.                 tabwidth = .ParagraphFormat.TabStops(1).Position - 2 * fontsize
  70.                 If .ComputeStatistics(1) <> .ComputeStatistics(4) And InStr(.Text, Chr(9)) <> 0 Then _
  71.                     setOptionSpacing .Duplicate, maxlen, k, tabwidth, olen  '行段数不一致则调整字符间距
  72.                 .ParagraphFormat.LeftIndent = 0  '假设无其他段落缩进
  73.                 .ParagraphFormat.CharacterUnitLeftIndent = 2
  74.             End With
  75.         Next
  76.     End With
  77.     Application.ScreenUpdating = True
  78. End Sub
复制代码

原来漏了一段:
  1. Sub setOptionSpacing(myRange As Range, maxlen%, pcount%, tabwidth!, olen)
  2.     Dim i%, j%, k%, n%
  3.         For i = 1 To myRange.ComputeStatistics(4)
  4.             With myRange.Paragraphs(i).Range
  5.                 If .ComputeStatistics(1) <> .ComputeStatistics(4) Then
  6.                     Do
  7.                         k = k + 1
  8.                         If j Mod pcount = 0 Then .End = .Start + olen(j) + 1 _
  9.                             Else .SetRange .End, .End + .MoveEndUntil(vbTab & Chr(13))
  10.                         If maxlen - olen(j) < 2 Then
  11.                             Do While .Characters.Last.Information(5) - .Information(5) > tabwidth _
  12.                                 Or .Characters.Last.Information(5) < .Information(5)
  13.                                 .Font.Spacing = -0.1 * n
  14.                                 If n < 6 Then n = n + 1 Else Exit Do
  15.                             Loop
  16.                             n = 0
  17.                         End If
  18.                         j = j + 1
  19.                     Loop Until k = pcount
  20.                     k = 0
  21.                 Else
  22.                     j = j + UBound(olen) / pcount
  23.                 End If
  24.             End With
  25.         Next
  26. End Sub
复制代码

评分

2

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-3-5 07:39 | 显示全部楼层
sylun 发表于 2024-3-4 22:05
可以试试如下代码,采用平分制表位定位:
原来漏了一段:

好,我测试一下,先谢谢

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-3-5 11:57 | 显示全部楼层
sylun 发表于 2024-3-4 22:05
可以试试如下代码,采用平分制表位定位:
原来漏了一段:

我手动可以设置成这种效果:
Snipaste_2024-03-05_11-57-26.jpg

TA的精华主题

TA的得分主题

发表于 2024-3-5 15:27 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
本帖最后由 batmanbbs 于 2024-3-5 15:35 编辑
小花鹿 发表于 2024-3-5 11:57
我手动可以设置成这种效果:

固定就是4个选项没有问题。分别就是一行1个选项,2个选项,4个选项。
先判断4个,每个选项的字数之和+3,小于页面宽度,一行放4个;
否则,判断第1选项和第3选项字符数取大,第2选项和第4选项字符数取大,两个大者相加+1,小于页面宽度,一行放2个,制表位就是第一组取大+1的位置;
否则,一行一个。

PS:这种方法不是平分方法,有时会显得比较乱,我还是喜欢用平分的方法

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-3-5 20:55 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
batmanbbs 发表于 2024-3-5 15:27
固定就是4个选项没有问题。分别就是一行1个选项,2个选项,4个选项。
先判断4个,每个选项的字数之和+3 ...

等待高手的出现

TA的精华主题

TA的得分主题

发表于 2024-3-5 21:43 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
小花鹿 发表于 2024-3-5 11:57
我手动可以设置成这种效果:

前面代码只是按全角字符对选项长度进行推算,对半角字符较多的选项有较大误差。现对代码稍作修改,并兼顾一行可平均排列五六个选项的情形,每题选项数6个以内不限。请楼主再测试,原9号题4选项本身可一行排满,如确需分两个段落,可修改代码。当然,代码并不适用于需要保留原字符格式或有图片图形的情形。
  1. Sub test2()
  2.     '试题选项对齐(最多6个选项),仅针对纯文本文档
  3.     Dim i%, j%, k%, fontsize%, colwidth!, maxlen%, tabwidth!
  4.     Dim qs, opt, olen
  5.     Dim Reg As Object, Matches As Object, Match As Object, aRange As Range
  6.    
  7.     Set Reg = CreateObject("vbscript.regexp")
  8.     With Reg
  9.         .Global = True
  10.         .MultiLine = True
  11.         .Pattern = "^\d+[\..]\s?.+?([A-F].+?)\r+(【答案】[A-F]+\r+)*(?=(^\d+\.|$))"
  12.         Set Matches = .Execute(ActiveDocument.Content.Text)
  13.         ReDim qs(2, Matches.Count - 1)
  14.         For Each Match In Matches
  15.             With Match
  16.                 qs(0, i) = .firstindex + InStr(.Value, Chr(13))
  17.                 qs(1, i) = qs(0, i) + Len(.SubMatches(0))
  18.                 qs(2, i) = Trim(.SubMatches(0))
  19.                 i = i + 1
  20.             End With
  21.         Next
  22.         
  23.         With ActiveDocument.Range(qs(0, 0), qs(0, 0))
  24.             fontsize = .Font.Size
  25.             colwidth = .PageSetup.TextColumns(1).Width
  26.         End With
  27.         .Pattern = "(?:^|[\s ]+)([A-F])[\..]"
  28.         For i = i - 1 To 0 Step -1
  29.             qs(2, i) = Replace(qs(2, i), Chr(9), "  ") '预防性替换
  30.             qs(2, i) = .Replace(qs(2, i), Chr(9) & "$1.")
  31.             qs(2, i) = Replace(qs(2, i), Chr(13), "")
  32.             qs(2, i) = Mid(qs(2, i), 2)
  33.             opt = Split(qs(2, i), Chr(9))
  34.             ReDim olen(UBound(opt))
  35.             For j = 0 To UBound(olen)
  36.                 olen(j) = Len(opt(j))
  37.             Next
  38.             maxlen = 0
  39.             For j = 0 To UBound(opt)
  40.                 If LenB(StrConv(opt(j), vbFromUnicode)) > maxlen Then maxlen = LenB(StrConv(opt(j), 128))
  41.             Next

  42.             Application.ScreenUpdating = False
  43.             Set aRange = ActiveDocument.Range(qs(0, i), qs(1, i))
  44.             With aRange
  45.                 With .ParagraphFormat  '根据字符数最多的选项设置制表位
  46.                     .TabStops.ClearAll
  47.                     Select Case fontsize * (maxlen / 2 - 2)
  48.                     Case Is > (colwidth - 2 * fontsize) / 2
  49.                         qs(2, i) = Replace(qs(2, i), Chr(9), Chr(13))
  50.                     Case Is > (colwidth - 2 * fontsize) / 4 Or j = 2
  51.                         .TabStops.Add (colwidth + 2 * fontsize) / 2
  52.                         If j > 2 Then qs(2, i) = Replace(qs(2, i), Chr(9) & "C.", Chr(13) & "C.")
  53.                         If j > 4 Then qs(2, i) = Replace(qs(2, i), Chr(9) & "E.", Chr(13) & "E.")
  54.                     Case Is < (colwidth - 2 * fontsize) / 6 And j = 6
  55.                         For k = 1 To 5
  56.                             .TabStops.Add 2 * fontsize + k * (colwidth - 2 * fontsize) / 6
  57.                         Next
  58.                     Case Is < (colwidth - 2 * fontsize) / 5 And j = 5
  59.                         For k = 1 To 4
  60.                             .TabStops.Add 2 * fontsize + k * (colwidth - 2 * fontsize) / 5
  61.                         Next
  62.                     Case Is < (colwidth - 2 * fontsize) / 3 And j <> 4
  63.                         .TabStops.Add (colwidth + 4 * fontsize) / 3
  64.                         .TabStops.Add 2 * (colwidth + fontsize) / 3
  65.                         If j > 3 Then qs(2, i) = Replace(qs(2, i), Chr(9) & "D.", Chr(13) & "D.")
  66.                     Case Else
  67.                         For k = 1 To 4
  68.                             .TabStops.Add 2 * fontsize + k * (colwidth - 2 * fontsize) / 4
  69.                         Next
  70.                     End Select
  71.                 End With
  72.                 .Text = qs(2, i)
  73.                 .End = .End + 1
  74.                
  75.                 k = (UBound(olen) + 1) / .ComputeStatistics(4)
  76.                 tabwidth = .ParagraphFormat.TabStops(1).Position - 2 * fontsize
  77.                 If .ComputeStatistics(1) <> .ComputeStatistics(4) And InStr(.Text, Chr(9)) <> 0 Then _
  78.                     setOptionSpacing .Duplicate, maxlen, k, tabwidth, olen  '行段数不一致则调整字符缩放
  79.                 .ParagraphFormat.LeftIndent = 0  '假设无其他段落缩进格式
  80.                 .ParagraphFormat.CharacterUnitLeftIndent = 2 '选项段落统一左缩进2字符
  81.             End With
  82.         Next
  83.     End With
  84.     Application.ScreenUpdating = True
  85. End Sub

  86. Sub setOptionSpacing(myRange As Range, maxlen%, pcount%, tabwidth!, olen)
  87.     Dim i%, j%, k%
  88.         For i = 1 To myRange.ComputeStatistics(4)
  89.             With myRange.Paragraphs(i).Range
  90.                 If .ComputeStatistics(1) <> .ComputeStatistics(4) Then
  91.                     Do
  92.                         k = k + 1
  93.                         If j Mod pcount = 0 Then .End = .Start + olen(j) + 1 _
  94.                             Else .SetRange .End, .End + .MoveEndUntil(vbTab & Chr(13))
  95.                         If maxlen / 2 - olen(j) < 0 Then .FitTextWidth = tabwidth - .Font.Size
  96.                         j = j + 1
  97.                     Loop Until k = pcount
  98.                     k = 0
  99.                 Else
  100.                     j = j + UBound(olen) / pcount
  101.                 End If
  102.             End With
  103.         Next
  104. End Sub
复制代码

TA的精华主题

TA的得分主题

发表于 2024-3-6 13:17 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
本帖最后由 batmanbbs 于 2024-3-6 19:29 编辑

已打包,见楼下附件

TA的精华主题

TA的得分主题

发表于 2024-3-6 13:25 | 显示全部楼层

非高手,基于sylun老师代码修改,非平分定位

【试卷】选项对齐(改写).zip

1.48 KB, 下载次数: 21

评分

3

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-3-6 17:42 | 显示全部楼层

TA的精华主题

TA的得分主题

 楼主| 发表于 2024-3-9 10:56 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
我找到完美解决方案了,就是先把选项转换成表格,再把表格转换成文本,分割符为制表符,就可以做到选项对齐了,不限选项个数,也能适用于格式文档(非纯文本)。

Snipaste_2024-03-09_10-54-30.jpg

Snipaste_2024-03-09_10-56-43.jpg
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

GMT+8, 2024-11-21 18:29 , Processed in 0.045311 second(s), 9 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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