Tools.bas 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188
  1. Attribute VB_Name = "Tools"
  2. '// This is free and unencumbered software released into the public domain.
  3. '// For more information, please refer to https://github.com/hongwenjun
  4. '// 简易火车排列
  5. Public Function Simple_Train_Arrangement(Space_Width As Double)
  6. API.BeginOpt
  7. Dim ssr As ShapeRange, s As Shape
  8. Dim cnt As Integer
  9. Set ssr = ActiveSelectionRange
  10. cnt = 1
  11. #If VBA7 Then
  12. ' ssr.sort " @shape1.top>@shape2.top"
  13. ssr.Sort " @shape1.left<@shape2.left"
  14. #Else
  15. ' X4 不支持 ShapeRange.sort 使用 lyvba32.dll 算法库排序 2023.07.08
  16. Set ssr = X4_Sort_ShapeRange(ssr, stlx)
  17. #End If
  18. ActiveDocument.ReferencePoint = cdrTopLeft
  19. For Each s In ssr
  20. '// 底对齐 If cnt > 1 Then s.SetPosition ssr(cnt - 1).RightX, ssr(cnt - 1).BottomY
  21. '// 改成顶对齐 2022-08-10
  22. ActiveDocument.ReferencePoint = cdrTopLeft + cdrBottomTop
  23. If cnt > 1 Then s.SetPosition ssr(cnt - 1).RightX + Space_Width, ssr(cnt - 1).TopY
  24. cnt = cnt + 1
  25. Next s
  26. API.EndOpt
  27. End Function
  28. '// 简易阶梯排列
  29. Public Function Simple_Ladder_Arrangement(Space_Width As Double)
  30. API.BeginOpt
  31. Dim ssr As ShapeRange, s As Shape
  32. Dim cnt As Integer
  33. Set ssr = ActiveSelectionRange
  34. cnt = 1
  35. #If VBA7 Then
  36. ssr.Sort " @shape1.top>@shape2.top"
  37. #Else
  38. ' X4 不支持 ShapeRange.sort 使用 lyvba32.dll 算法库排序 2023.07.08
  39. Set ssr = X4_Sort_ShapeRange(ssr, stty).ReverseRange
  40. #End If
  41. ActiveDocument.ReferencePoint = cdrTopLeft
  42. For Each s In ssr
  43. If cnt > 1 Then s.SetPosition ssr(cnt - 1).LeftX, ssr(cnt - 1).BottomY - Space_Width
  44. cnt = cnt + 1
  45. Next s
  46. API.EndOpt
  47. End Function
  48. '// 文本转曲线 默认使用简单转曲,参数 all=1 ,支持框选和图框剪裁内的文本
  49. Public Function TextShape_ConvertToCurves(Optional all = 0)
  50. API.BeginOpt
  51. On Error GoTo ErrorHandler
  52. Dim s As Shape, cnt As Long
  53. If all = 1 Then
  54. For Each s In API.FindAllShapes.Shapes.FindShapes(, cdrTextShape)
  55. s.ConvertToCurves
  56. cnt = cnt + 1
  57. Next s
  58. Else
  59. For Each s In ActivePage.FindShapes(, cdrTextShape)
  60. s.ConvertToCurves
  61. cnt = cnt + 1
  62. Next s
  63. End If
  64. ErrorHandler:
  65. API.EndOpt
  66. End Function
  67. '// 复制物件
  68. Public Function copy_shape()
  69. Dim OrigSelection As ShapeRange
  70. Set OrigSelection = ActiveSelectionRange
  71. OrigSelection.Copy
  72. End Function
  73. '// 旋转物件角度
  74. Public Function Rotate_Shapes(n As Double)
  75. API.BeginOpt
  76. Dim sh As Shape, shs As Shapes
  77. Set shs = ActiveSelection.Shapes
  78. Dim s As String, size As String
  79. For Each sh In shs
  80. sh.Rotate n
  81. Next sh
  82. API.EndOpt
  83. End Function
  84. '// 得到物件尺寸
  85. Public Function get_shape_size(ByRef sx As Double, ByRef sy As Double)
  86. ActiveDocument.Unit = cdrMillimeter
  87. Dim sh As ShapeRange
  88. Set sh = ActiveSelectionRange
  89. sx = sh.SizeWidth
  90. sy = sh.SizeHeight
  91. sx = Int(sx * 100 + 0.5) / 100
  92. sy = Int(sy * 100 + 0.5) / 100
  93. End Function
  94. '// 批量设置物件尺寸
  95. Public Function Set_Shapes_size(ByRef sx As Double, ByRef sy As Double)
  96. API.BeginOpt
  97. ActiveDocument.ReferencePoint = cdrCenter
  98. Dim sh As Shape, shs As Shapes
  99. Set shs = ActiveSelection.Shapes
  100. Dim s As String, size As String
  101. For Each sh In shs
  102. sh.SizeWidth = sx
  103. sh.SizeHeight = sy
  104. Next sh
  105. API.EndOpt
  106. End Function
  107. '// 批量设置物件尺寸整数
  108. Public Function Size_to_Integer()
  109. If 0 = ActiveSelectionRange.Count Then Exit Function
  110. API.BeginOpt
  111. '// 修改变形尺寸基准
  112. ActiveDocument.ReferencePoint = cdrCenter
  113. Dim sh As Shape, shs As Shapes
  114. Set shs = ActiveSelection.Shapes
  115. Dim s As String, size As String
  116. For Each sh In shs
  117. size = Int(sh.SizeWidth + 0.5) & "x" & Int(sh.SizeHeight + 0.5) & "mm"
  118. sh.SetSize Int(sh.SizeWidth + 0.5), Int(sh.SizeHeight + 0.5)
  119. s = s & size & vbNewLine
  120. Next sh
  121. API.WriteClipBoard s
  122. API.EndOpt
  123. MsgBox "Object Size Information To Clipboard:" & vbNewLine & s & vbNewLine
  124. End Function
  125. '// 设置物件页面居中
  126. Public Function Align_Page_Center()
  127. If 0 = ActiveSelectionRange.Count Then Exit Function
  128. '// 实践应用: 选择物件群组,页面设置物件大小,物件页面居中
  129. API.BeginOpt
  130. Dim OrigSelection As ShapeRange, sh As Shape
  131. Set OrigSelection = ActiveSelectionRange
  132. Set sh = OrigSelection.Group
  133. ActivePage.SetSize Int(sh.SizeWidth + 0.9), Int(sh.SizeHeight + 0.9)
  134. #If VBA7 Then
  135. ActiveDocument.ClearSelection
  136. sh.AddToSelection
  137. ActiveSelection.AlignAndDistribute 3, 3, 2, 0, False, 2
  138. #Else
  139. sh.AlignToPageCenter cdrAlignHCenter + cdrAlignVCenter
  140. #End If
  141. API.EndOpt
  142. End Function
  143. '''/// 使用Python脚本 整理尺寸 提取条码数字 建立二维码 位图转文本 ///'''
  144. Public Function Python_Organize_Size()
  145. On Error GoTo ErrorHandler
  146. mypy = Path & "GMS\LYVBA\Organize_Size.py"
  147. cmd_line = "pythonw " & Chr(34) & mypy & Chr(34)
  148. Shell cmd_line
  149. ErrorHandler:
  150. End Function
  151. Public Function Python_Get_Barcode_Number()
  152. On Error GoTo ErrorHandler
  153. mypy = Path & "GMS\LYVBA\Get_Barcode_Number.py"
  154. cmd_line = "pythonw " & Chr(34) & mypy & Chr(34)
  155. Shell cmd_line
  156. ErrorHandler:
  157. End Function
  158. Public Function Python_BITMAP()
  159. On Error GoTo ErrorHandler
  160. mypy = Path & "GMS\LYVBA\BITMAP.py"
  161. cmd_line = "pythonw " & Chr(34) & mypy & Chr(34)
  162. Shell cmd_line
  163. ErrorHandler:
  164. End Function
  165. Public Function Python_BITMAP2()
  166. On Error GoTo ErrorHandler
  167. Bitmap = "C:\TSP\BITMAP.exe"
  168. Shell Bitmap
  169. ErrorHandler:
  170. End Function
  171. Public Function Python_Make_QRCode()
  172. On Error GoTo ErrorHandler
  173. mypy = Path & "GMS\LYVBA\Make_QRCode.py"
  174. cmd_line = "pythonw " & Chr(34) & mypy & Chr(34)
  175. Shell cmd_line
  176. ErrorHandler:
  177. End Function
  178. '// QRCode二维码制作
  179. Public Function QRCode_replace()
  180. On Error GoTo ErrorHandler
  181. API.BeginOpt
  182. Dim image_path As String
  183. image_path = API.GetClipBoardString
  184. ActiveDocument.ReferencePoint = cdrCenter
  185. Dim sh As Shape, shs As Shapes, cs As Shape
  186. Dim X As Double, Y As Double
  187. Set shs = ActiveSelection.Shapes
  188. cnt = 0
  189. For Each sh In shs
  190. If cnt = 0 Then
  191. ActiveDocument.ClearSelection
  192. ActiveLayer.Import image_path
  193. Set sc = ActiveSelection
  194. cnt = 1
  195. Else
  196. sc.Duplicate 0, 0
  197. End If
  198. sh.GetPosition X, Y
  199. sc.SetPosition X, Y
  200. sh.GetSize X, Y
  201. sc.SetSize X, Y
  202. sh.Delete
  203. Next sh
  204. ErrorHandler:
  205. API.EndOpt
  206. End Function
  207. '// QRCode二维码转矢量图
  208. Public Function QRCode_to_Vector()
  209. On Error GoTo ErrorHandler
  210. Set sr = ActiveSelectionRange
  211. With sr(1).Bitmap.Trace(cdrTraceHighQualityImage)
  212. .TraceType = cdrTraceHighQualityImage
  213. .Smoothing = 50 '数值小则平滑,数值大则细节多
  214. .RemoveBackground = False
  215. .DeleteOriginalObject = True
  216. .Finish
  217. End With
  218. Exit Function
  219. ErrorHandler:
  220. On Error Resume Next
  221. End Function
  222. '''//// 选择多物件,组合然后拆分线段,为角线爬虫准备 ////'''
  223. Public Function Split_Segment()
  224. On Error GoTo ErrorHandler
  225. API.BeginOpt
  226. Dim ssr As ShapeRange, s As Shape
  227. Dim nr As NodeRange, nd As Node
  228. Set ssr = ActiveSelectionRange
  229. Set s = ssr.UngroupAllEx.Combine
  230. Set nr = s.Curve.Nodes.all
  231. nr.BreakApart
  232. s.BreakApartEx
  233. ' For Each nd In nr
  234. ' nd.BreakApart
  235. ' Next nd
  236. ErrorHandler:
  237. API.EndOpt
  238. End Function
  239. '''//// 标记画框 支持容差 ////'''
  240. Public Function Mark_CreateRectangle(expand As Boolean)
  241. On Error GoTo ErrorHandler
  242. API.BeginOpt
  243. ActiveDocument.ReferencePoint = cdrBottomLeft
  244. Dim ssr As ShapeRange
  245. Dim sh As Shape, tr As Double
  246. Set ssr = ActiveSelectionRange
  247. tr = 0
  248. If GlobalUserData.Exists("Tolerance", 1) Then
  249. tr = Val(GlobalUserData("Tolerance", 1))
  250. End If
  251. For Each sh In ssr
  252. If expand = False Then
  253. mark_shape sh
  254. Else
  255. mark_shape_expand sh, tr
  256. End If
  257. Next sh
  258. ErrorHandler:
  259. API.EndOpt
  260. End Function
  261. Private Function mark_shape_expand(sh As Shape, tr As Double)
  262. Dim s As Shape
  263. Dim X As Double, Y As Double, w As Double, h As Double, r As Double
  264. sh.GetBoundingBox X, Y, w, h
  265. X = X - tr: Y = Y - tr: w = w + 2 * tr: h = h + 2 * tr
  266. r = Max(w, h) / Min(w, h) / 30 * Math.Sqr(w * h)
  267. If w < h Then
  268. Set s = ActiveLayer.CreateRectangle2(X - r, Y, w + 2 * r, h)
  269. Else
  270. Set s = ActiveLayer.CreateRectangle2(X, Y - r, w, h + 2 * r)
  271. End If
  272. s.Outline.SetProperties Color:=CreateRGBColor(0, 255, 0)
  273. End Function
  274. Private Function mark_shape(sh As Shape)
  275. Dim s As Shape
  276. Dim X As Double, Y As Double, w As Double, h As Double
  277. sh.GetBoundingBox X, Y, w, h, True
  278. Set s = ActiveLayer.CreateRectangle2(X, Y, w, h)
  279. s.Outline.SetProperties Color:=CreateRGBColor(0, 255, 0)
  280. End Function
  281. Private Function Max(ByVal a, ByVal b)
  282. If a < b Then
  283. a = b
  284. End If
  285. Max = a
  286. End Function
  287. Private Function Min(ByVal a, ByVal b)
  288. If a > b Then
  289. a = b
  290. End If
  291. Min = a
  292. End Function
  293. '''//// 批量组合合并 ////'''
  294. Public Function Batch_Combine()
  295. On Error GoTo ErrorHandler
  296. API.BeginOpt
  297. Dim ssr As ShapeRange, sh As Shape
  298. Set ssr = ActiveSelectionRange
  299. For Each sh In ssr
  300. sh.UngroupAllEx.Combine
  301. Next sh
  302. ErrorHandler:
  303. API.EndOpt
  304. End Function
  305. '''//// 一键拆开多行组合的文字字符 ////''' ''' 本功能由群友半缘君赞助发行 '''
  306. Public Function Take_Apart_Character()
  307. On Error GoTo ErrorHandler
  308. API.BeginOpt
  309. ActiveDocument.ReferencePoint = cdrBottomLeft
  310. Dim ssr As ShapeRange
  311. Dim s1 As Shape, sh As Shape, s As Shape
  312. Dim tr As Double
  313. Set ssr = ActiveSelectionRange
  314. '// 记忆选择范围
  315. Dim X As Double, Y As Double, w As Double, h As Double
  316. ssr.GetBoundingBox X, Y, w, h
  317. Set s1 = ActiveLayer.CreateRectangle2(X, Y, w, h)
  318. '// 解散群组,先组合,再散开
  319. Set s = ssr.UngroupAllEx.Combine
  320. Set ssr = s.BreakApartEx
  321. '// 读取容差值
  322. tr = 0
  323. If GlobalUserData.Exists("Tolerance", 1) Then
  324. tr = Val(GlobalUserData("Tolerance", 1))
  325. End If
  326. '// 标记画框,选择标记框
  327. For Each sh In ssr
  328. mark_shape_expand sh, tr
  329. Next sh
  330. Set ssr = ActivePage.Shapes.FindShapes(Query:="@colors.find(RGB(0, 255, 0))")
  331. ActiveDocument.ClearSelection
  332. ssr.AddToSelection
  333. '// 调用 智能群组 后删除标记画框
  334. SmartGroup.Smart_Group
  335. ActiveDocument.BeginCommandGroup: Application.Optimization = True
  336. ssr.Delete
  337. Set sh = ActivePage.SelectShapesFromRectangle(s1.LeftX, s1.TopY, s1.RightX, s1.BottomY, False)
  338. ' sh.Shapes.All.Group
  339. s1.Delete
  340. '// 通过s1矩形范围选择群组后合并组合
  341. For Each s In sh.Shapes
  342. s.UngroupAllEx.Combine
  343. Next s
  344. ErrorHandler:
  345. API.EndOpt
  346. End Function
  347. '''//// 简单一刀切 识别群组 ////''' ''' 本功能由群友宏瑞广告赞助发行 '''
  348. Public Function Single_Line()
  349. If 0 = ActiveSelectionRange.Count Then Exit Function
  350. On Error GoTo ErrorHandler
  351. API.BeginOpt
  352. Dim cm(2) As Color
  353. Set cm(0) = CreateRGBColor(0, 255, 0) ' RGB 绿
  354. Set cm(1) = CreateRGBColor(255, 0, 0) ' RGB 红
  355. Dim ssr As ShapeRange
  356. Dim SrNew As New ShapeRange
  357. Dim s As Shape, s1 As Shape, line As Shape, line2 As Shape
  358. Dim cnt As Integer
  359. cnt = 1
  360. If 1 = ActiveSelectionRange.Count Then
  361. Set ssr = ActiveSelectionRange(1).UngroupAllEx
  362. Else
  363. Set ssr = ActiveSelectionRange
  364. End If
  365. '// 记忆选择范围
  366. Dim X As Double, Y As Double, w As Double, h As Double
  367. ssr.GetBoundingBox X, Y, w, h
  368. Set s1 = ActiveLayer.CreateRectangle2(X, Y, w, h)
  369. s1.Outline.SetProperties Color:=cm(0)
  370. SrNew.Add s1
  371. #If VBA7 Then
  372. ' ssr.sort " @shape1.top>@shape2.top"
  373. ssr.Sort " @shape1.left<@shape2.left"
  374. #Else
  375. ' X4 不支持 ShapeRange.sort
  376. #End If
  377. '// 相交 Set line2 = line.Intersect(s, True, True)
  378. '// 判断相交 line.Curve.IntersectsWith(s.Curve)
  379. For Each s In ssr
  380. If cnt > 1 Then
  381. s.ConvertToCurves
  382. Set line = ActiveLayer.CreateLineSegment(s.LeftX, s.TopY, s.LeftX, s.TopY - s.SizeHeight)
  383. line.Outline.SetProperties Color:=cm(1)
  384. SrNew.Add line
  385. End If
  386. cnt = cnt + 1
  387. Next s
  388. SrNew.Group
  389. ErrorHandler:
  390. API.EndOpt
  391. End Function
  392. Public Function Single_Line_Vertical()
  393. If 0 = ActiveSelectionRange.Count Then Exit Function
  394. On Error GoTo ErrorHandler
  395. API.BeginOpt
  396. Dim cm(2) As Color
  397. Set cm(0) = CreateRGBColor(0, 255, 0) ' RGB 绿
  398. Set cm(1) = CreateRGBColor(255, 0, 0) ' RGB 红
  399. Dim ssr As ShapeRange
  400. Dim SrNew As New ShapeRange
  401. Dim s As Shape, s1 As Shape, line As Shape, line2 As Shape
  402. Dim cnt As Integer
  403. cnt = 1
  404. If 1 = ActiveSelectionRange.Count Then
  405. Set ssr = ActiveSelectionRange(1).UngroupAllEx
  406. Else
  407. Set ssr = ActiveSelectionRange
  408. End If
  409. '// 记忆选择范围
  410. Dim X As Double, Y As Double, w As Double, h As Double
  411. ssr.GetBoundingBox X, Y, w, h
  412. Set s1 = ActiveLayer.CreateRectangle2(X, Y, w, h)
  413. s1.Outline.SetProperties Color:=cm(0)
  414. SrNew.Add s1
  415. #If VBA7 Then
  416. ssr.Sort " @shape1.top>@shape2.top"
  417. #Else
  418. ' X4 不支持 ShapeRange.sort
  419. #End If
  420. For Each s In ssr
  421. If cnt > 1 Then
  422. s.ConvertToCurves
  423. Set line = ActiveLayer.CreateLineSegment(s.LeftX, s.TopY, s.RightX, s.TopY)
  424. line.Outline.SetProperties Color:=cm(1)
  425. SrNew.Add line
  426. End If
  427. cnt = cnt + 1
  428. Next s
  429. SrNew.Group
  430. ErrorHandler:
  431. API.EndOpt
  432. End Function
  433. Public Function Single_Line_LastNode()
  434. If 0 = ActiveSelectionRange.Count Then Exit Function
  435. On Error GoTo ErrorHandler
  436. API.BeginOpt
  437. Dim cm(2) As Color
  438. Set cm(0) = CreateRGBColor(0, 255, 0) ' RGB 绿
  439. Set cm(1) = CreateRGBColor(255, 0, 0) ' RGB 红
  440. Dim ssr As ShapeRange
  441. Dim SrNew As New ShapeRange
  442. Dim s As Shape, s1 As Shape, line As Shape, line2 As Shape
  443. Dim cnt As Integer
  444. cnt = 1
  445. If 1 = ActiveSelectionRange.Count Then
  446. Set ssr = ActiveSelectionRange(1).UngroupAllEx
  447. Else
  448. Set ssr = ActiveSelectionRange
  449. End If
  450. ' 记忆选择范围
  451. Dim X As Double, Y As Double, w As Double, h As Double
  452. ssr.GetBoundingBox X, Y, w, h
  453. Set s1 = ActiveLayer.CreateRectangle2(X, Y, w, h)
  454. s1.Outline.SetProperties Color:=cm(0)
  455. SrNew.Add s1
  456. #If VBA7 Then
  457. ssr.Sort " @shape1.left<@shape2.left"
  458. #Else
  459. ' X4 不支持 ShapeRange.sort
  460. #End If
  461. Dim nr As NodeRange
  462. For Each s In ssr
  463. If cnt > 1 Then
  464. Set nr = s.DisplayCurve.Nodes.all
  465. Set line = ActiveLayer.CreateLineSegment(nr.FirstNode.PositionX, nr.FirstNode.PositionY, nr.LastNode.PositionX, nr.LastNode.PositionY)
  466. line.Outline.SetProperties Color:=cm(1)
  467. SrNew.Add line
  468. End If
  469. cnt = cnt + 1
  470. Next s
  471. SrNew.Group
  472. ErrorHandler:
  473. API.EndOpt
  474. End Function
  475. '''//// 选择范围画框 ////'''
  476. Public Function Mark_Range_Box()
  477. If 0 = ActiveSelectionRange.Count Then Exit Function
  478. ActiveDocument.Unit = cdrMillimeter
  479. Dim s1 As Shape, ssr As ShapeRange
  480. Set ssr = ActiveSelectionRange
  481. Dim X As Double, Y As Double, w As Double, h As Double
  482. ssr.GetBoundingBox X, Y, w, h
  483. Set s1 = ActiveLayer.CreateRectangle2(X, Y, w, h)
  484. s1.Outline.SetProperties Color:=CreateRGBColor(0, 255, 0) '// RGB 绿
  485. End Function
  486. '''//// 快速颜色选择 ////'''
  487. Function quickColorSelect()
  488. Dim X As Double, Y As Double
  489. Dim s As Shape, s1 As Shape
  490. Dim sr As ShapeRange, sr2 As ShapeRange
  491. Dim Shift As Long, bClick As Boolean
  492. Dim c As New Color, c2 As New Color
  493. EventsEnabled = False
  494. Set sr = ActivePage.Shapes.FindShapes(Query:="@fill.type = 'uniform'")
  495. ActiveDocument.ClearSelection
  496. bClick = False
  497. While Not bClick
  498. On Error Resume Next
  499. bClick = ActiveDocument.GetUserClick(X, Y, Shift, 10, False, cdrCursorPickNone)
  500. If Not bClick Then
  501. Set s = ActivePage.SelectShapesAtPoint(X, Y, False)
  502. Set s = s.Shapes.Last
  503. c2.CopyAssign s.Fill.UniformColor
  504. Set sr2 = New ShapeRange
  505. For Each s1 In sr.Shapes
  506. c.CopyAssign s1.Fill.UniformColor
  507. If c.IsSame(c2) Then
  508. sr2.Add s1
  509. End If
  510. Next s1
  511. sr2.CreateSelection
  512. ActiveWindow.Refresh
  513. End If
  514. Wend
  515. EventsEnabled = True
  516. End Function
  517. '''//// 切割图形-垂直分割-水平分割 ////'''
  518. Function divideVertically()
  519. If 0 = ActiveSelectionRange.Count Then Exit Function
  520. On Error GoTo ErrorHandler
  521. ActiveDocument.BeginCommandGroup: Application.Optimization = True
  522. cutInHalf 1
  523. ActiveDocument.EndCommandGroup
  524. Application.Optimization = False
  525. ActiveWindow.Refresh: Application.Refresh
  526. Exit Function
  527. ErrorHandler:
  528. Application.Optimization = False
  529. On Error Resume Next
  530. End Function
  531. Function divideHorizontally()
  532. If 0 = ActiveSelectionRange.Count Then Exit Function
  533. On Error GoTo ErrorHandler
  534. ActiveDocument.BeginCommandGroup: Application.Optimization = True
  535. cutInHalf 2
  536. ActiveDocument.EndCommandGroup
  537. Application.Optimization = False
  538. ActiveWindow.Refresh: Application.Refresh
  539. Exit Function
  540. ErrorHandler:
  541. Application.Optimization = False
  542. On Error Resume Next
  543. End Function
  544. Private Function cutInHalf(Optional method As Integer)
  545. Dim s As Shape, rect As Shape, rect2 As Shape
  546. Dim trimmed1 As Shape, trimmed2 As Shape
  547. Dim X As Double, Y As Double, w As Double, h As Double
  548. Dim vBool As Boolean
  549. Dim leeway As Double
  550. Dim sr As ShapeRange, sr2 As New ShapeRange
  551. vBool = True
  552. If method = 2 Then
  553. vBool = False
  554. End If
  555. leeway = 0.1
  556. Set sr = ActiveSelectionRange
  557. ActiveDocument.BeginCommandGroup "Cut in half"
  558. For Each s In sr
  559. s.GetBoundingBox X, Y, w, h
  560. If (vBool) Then
  561. 'vertical slice
  562. Set rect = ActiveLayer.CreateRectangle2(X - leeway, Y - leeway, (w / 2) + leeway, h + (leeway * 2))
  563. Set rect2 = ActiveLayer.CreateRectangle2(X + (w / 2), Y - leeway, (w / 2) + leeway, h + (leeway * 2))
  564. Else
  565. Set rect = ActiveLayer.CreateRectangle2(X - leeway, Y - leeway, w + (leeway * 2), (h / 2) + leeway)
  566. Set rect2 = ActiveLayer.CreateRectangle2(X - leeway, Y + (h / 2), w + (leeway * 2), (h / 2) + leeway)
  567. End If
  568. Set trimmed1 = rect.Intersect(s, True, True)
  569. rect.Delete
  570. Set trimmed2 = rect2.Intersect(s, True, True)
  571. s.Delete
  572. rect2.Delete
  573. sr2.Add trimmed1
  574. sr2.Add trimmed2
  575. Next s
  576. ActiveDocument.EndCommandGroup
  577. sr2.CreateSelection
  578. End Function
  579. '// 批量多页居中-遍历批量物件,放置物件到页面
  580. Public Function Batch_Align_Page_Center()
  581. If 0 = ActiveSelectionRange.Count Then Exit Function
  582. On Error GoTo ErrorHandler
  583. API.BeginOpt
  584. Set sr = ActiveSelectionRange
  585. total = sr.Count
  586. '// 建立多页面
  587. Set doc = ActiveDocument
  588. doc.AddPages (total - 1)
  589. #If VBA7 Then
  590. sr.Sort " @shape1.Top * 100 - @shape1.Left > @shape2.Top * 100 - @shape2.Left"
  591. #Else
  592. ' X4 不支持 ShapeRange.sort
  593. Set sr = X4_Sort_ShapeRange(ssr, topWt_left).ReverseRange
  594. #End If
  595. Dim sh As Shape
  596. '// 遍历批量物件,放置物件到页面
  597. For i = 1 To sr.Count
  598. doc.Pages(i).Activate
  599. Set sh = sr.Shapes(i)
  600. ActivePage.SetSize Int(sh.SizeWidth + 0.9), Int(sh.SizeHeight + 0.9)
  601. sh.MoveToLayer ActivePage.ActiveLayer
  602. '// 物件居中页面
  603. #If VBA7 Then
  604. ActiveDocument.ClearSelection
  605. sh.AddToSelection
  606. ActiveSelection.AlignAndDistribute 3, 3, 2, 0, False, 2
  607. #Else
  608. sh.AlignToPageCenter cdrAlignHCenter + cdrAlignVCenter
  609. #End If
  610. Next i
  611. ErrorHandler:
  612. API.EndOpt
  613. End Function
  614. '// 安全线: 点击一次建立辅助线,再调用清除参考线
  615. Public Function guideangle(actnumber As ShapeRange, cardblood As Integer)
  616. Dim sr As ShapeRange
  617. Set sr = ActiveDocument.MasterPage.GuidesLayer.FindShapes(Type:=cdrGuidelineShape)
  618. If sr.Count <> 0 Then
  619. sr.Delete
  620. Exit Function
  621. End If
  622. If 0 = ActiveSelectionRange.Count Then Exit Function
  623. ActiveDocument.Unit = cdrMillimeter
  624. With actnumber
  625. Set s1 = ActiveDocument.MasterPage.GuidesLayer.CreateGuideAngle(0, .TopY - cardblood, 0#)
  626. Set s1 = ActiveDocument.MasterPage.GuidesLayer.CreateGuideAngle(0, .BottomY + cardblood, 0#)
  627. Set s1 = ActiveDocument.MasterPage.GuidesLayer.CreateGuideAngle(.LeftX + cardblood, 0, 90#)
  628. Set s1 = ActiveDocument.MasterPage.GuidesLayer.CreateGuideAngle(.RightX - cardblood, 0, 90#)
  629. End With
  630. End Function
  631. '// 标注尺寸 批量简单标注数字
  632. Public Function Simple_Label_Numbers()
  633. API.BeginOpt
  634. Set sr = ActiveSelectionRange
  635. For Each s In sr.Shapes
  636. X = s.CenterX: Y = s.TopY
  637. sw = s.SizeWidth: sh = s.SizeHeight
  638. text = Int(sw + 0.5) & "x" & Int(sh + 0.5) & "mm"
  639. Set s = ActiveLayer.CreateArtisticText(0, 0, text)
  640. s.CenterX = X: s.BottomY = Y + 5
  641. Next
  642. API.EndOpt
  643. End Function
  644. '// 修复圆角缺角到直角
  645. Public Function corner_off()
  646. API.BeginOpt
  647. Dim os As ShapeRange
  648. Dim s As Shape, fir As Shape, ci As Shape
  649. Dim nd As Node, nds As Node, nde As Node
  650. Set os = ActiveSelectionRange
  651. On Error GoTo errn
  652. selec = False
  653. If os.Shapes.Count = 1 Then
  654. Set s = os.FirstShape
  655. If Not s.Curve Is Nothing Then
  656. For Each nd In s.Curve.Nodes
  657. If nd.Selected Then
  658. selec = True
  659. Exit For
  660. End If
  661. Next nd
  662. End If
  663. End If
  664. If os.Shapes.Count > 1 Or Not selec Then
  665. os.ConvertToCurves
  666. For Each s In os.Shapes
  667. Set nds = Nothing
  668. Set nde = Nothing
  669. For k = 1 To 3
  670. For i = 1 To s.Curve.Nodes.Count
  671. If i <= s.Curve.Nodes.Count Then
  672. Set nd = s.Curve.Nodes(i)
  673. If Not nd.NextSegment Is Nothing And Not nd.PrevSegment Is Nothing Then
  674. If Abs(nd.PrevSegment.Length - nd.NextSegment.Length) < (nd.PrevSegment.Length + nd.NextSegment.Length) / 30 And nd.PrevSegment.Type = cdrCurveSegment And nd.NextSegment.Type = cdrCurveSegment Then
  675. corner_off_make s, nd.Previous, nd.Next
  676. ElseIf Not nd.Next.NextSegment Is Nothing Then
  677. If (nd.PrevSegment.Type = cdrLineSegment Or Abs(Abs(nd.PrevSegment.StartingControlPointAngle - nd.PrevSegment.EndingControlPointAngle) - 180) < 1) _
  678. And (nd.Next.NextSegment.Type = cdrLineSegment Or Abs(Abs(nd.Next.NextSegment.StartingControlPointAngle - nd.Next.NextSegment.EndingControlPointAngle) - 180) < 1) _
  679. And nd.NextSegment.Type = cdrCurveSegment Then
  680. corner_off_make s, nd, nd.Next
  681. End If
  682. End If
  683. End If
  684. End If
  685. Next i
  686. Next k
  687. Next s
  688. ElseIf os.Shapes.Count = 1 And selec Then
  689. Set nds = Nothing
  690. Set nde = Nothing
  691. For Each nd In s.Curve.Nodes
  692. If Not nd.Selected And Not nd.Next.Selected Then Exit For
  693. Next nd
  694. If Not nd Is s.Curve.Nodes.Last Then
  695. For i = 1 To s.Curve.Nodes.Count
  696. Set nd = nd.Next
  697. If Not nde Is Nothing And Not nds Is Nothing And Not nd.Selected Then Exit For
  698. If Not nds Is Nothing And nd.Selected Then Set nde = nd
  699. If nde Is Nothing And nds Is Nothing And nd.Selected Then Set nds = nd
  700. Next i
  701. If Not nds Is Nothing And Not nde Is Nothing Then
  702. 'ActiveLayer.CreateEllipse2 nds.PositionX, nds.PositionY, nde.PrevSegment.Length / 4
  703. 'ActiveLayer.CreateEllipse2 nde.PositionX, nde.PositionY, nde.PrevSegment.Length / 4
  704. corner_off_make s, nds, nde
  705. End If
  706. End If
  707. End If
  708. errn:
  709. API.EndOpt
  710. End Function
  711. Private Function corner_off_make(s As Shape, nds As Node, nde As Node)
  712. Dim l1 As Shape, l2 As Shape
  713. Dim os As ShapeRange
  714. Dim ss As Shape
  715. Set l1 = ActiveLayer.CreateLineSegment(nds.PositionX, nds.PositionY, nds.PositionX + s.SizeWidth * 3, nds.PositionY)
  716. l1.RotationCenterX = nds.PositionX
  717. l1.RotationAngle = nds.PrevSegment.EndingControlPointAngle + 180
  718. Set l2 = ActiveLayer.CreateLineSegment(nde.PositionX, nde.PositionY, nde.PositionX + s.SizeWidth * 3, nde.PositionY)
  719. l2.RotationCenterX = nde.PositionX
  720. l2.RotationAngle = nde.NextSegment.StartingControlPointAngle + 180
  721. Set lcross = l2.Curve.Segments.First.GetIntersections(l1.Curve.Segments.First)
  722. If lcross.Count > 0 Then
  723. cx = lcross(1).PositionX
  724. cy = lcross(1).PositionY
  725. sx = nds.PositionX
  726. sy = nds.PositionY
  727. ex = nde.PositionX
  728. ey = nde.PositionY
  729. l1.Curve.Nodes.Last.PositionX = cx
  730. l1.Curve.Nodes.Last.PositionY = cy
  731. l2.Curve.Nodes.Last.PositionX = cx
  732. l2.Curve.Nodes.Last.PositionY = cy
  733. s.Curve.Nodes.Range(Array(nds.AbsoluteIndex, nde.AbsoluteIndex)).BreakApart
  734. Set os = s.BreakApartEx
  735. oscnt = os.Shapes.Count
  736. For Each ss In os.Shapes
  737. If ss.Curve.Nodes.First.PositionX = ex And ss.Curve.Nodes.First.PositionY = ey Then Set s2 = ss
  738. If ss.Curve.Nodes.Last.PositionX = sx And ss.Curve.Nodes.Last.PositionY = sy Then Set s1 = ss
  739. If ss.Curve.Nodes.First.PositionX = sx And ss.Curve.Nodes.First.PositionY = sy Then ss.Delete
  740. Next ss
  741. If s1.Curve.Segments.Last.Type = cdrLineSegment Or Abs(Abs(s1.Curve.Segments.Last.StartingControlPointAngle - s1.Curve.Segments.Last.EndingControlPointAngle) - 180) < 1 Then
  742. s1.Curve.Nodes.Last.PositionX = lcross(1).PositionX
  743. s1.Curve.Nodes.Last.PositionY = lcross(1).PositionY
  744. l1.Delete
  745. Else
  746. Set s1 = l1.Weld(s1)
  747. End If
  748. If oscnt = 2 Then Set s2 = s1
  749. If s2.Curve.Segments.First.Type = cdrLineSegment Or Abs(Abs(s2.Curve.Segments.First.StartingControlPointAngle - s2.Curve.Segments.First.EndingControlPointAngle) - 180) < 1 Then
  750. s2.Curve.Nodes.First.PositionX = lcross(1).PositionX
  751. s2.Curve.Nodes.First.PositionY = lcross(1).PositionY
  752. l2.Delete
  753. Else
  754. Set s2 = l2.Weld(s2)
  755. End If
  756. If oscnt > 2 Then Set s2 = s1.Weld(s2)
  757. s2.CustomCommand "ConvertTo", "JoinCurves", 0.1
  758. Set s = s2
  759. Else
  760. l1.Delete
  761. l2.Delete
  762. End If
  763. End Function
  764. Public Function autogroup(Optional Group As String = "group", Optional shft = 0, Optional sss As Shapes = Nothing, Optional undogroup = True) As ShapeRange
  765. Dim sr As ShapeRange, sr_all As ShapeRange, os As ShapeRange
  766. Dim sp As SubPaths
  767. Dim arr()
  768. Dim s As Shape
  769. If sss Is Nothing Then Set os = ActiveSelectionRange Else Set os = sss.all
  770. On Error GoTo errn
  771. ActiveDocument.BeginCommandGroup: Application.Optimization = True
  772. If ActiveSelection.Shapes.Count > 0 Then
  773. gcnt = os.Shapes.Count
  774. ReDim arr(1 To gcnt, 1 To gcnt)
  775. Set sr_all = ActiveSelectionRange
  776. sr_all.RemoveAll
  777. ReDim arr(1 To gcnt, 1 To gcnt)
  778. ActiveDocument.Unit = cdrTenthMicron
  779. sgap = 10
  780. If shft = 2 Or shft = 3 Or shft = 6 Or shft = 7 Then
  781. os.RemoveAll
  782. For Each s In ActiveSelectionRange.Shapes
  783. os.Add ActivePage.SelectShapesFromRectangle(s.LeftX - sgap, s.BottomY - sgap, s.RightX + sgap, s.TopY + sgap, True)
  784. Next s
  785. End If
  786. For i = 1 To os.Shapes.Count
  787. Set s1 = os.Shapes(i)
  788. arr(i, i) = i
  789. For j = 1 To os.Shapes.Count
  790. Set s2 = os.Shapes(j)
  791. If s2.LeftX < s1.RightX + sgap And s2.RightX > s1.LeftX - sgap And s2.BottomY < s1.TopY + sgap And s2.TopY > s1.BottomY - sgap Then
  792. If shft = 1 Or shft = 3 Or shft = 5 Or shft = 7 Then
  793. Set isec = s1.Intersect(s2)
  794. If Not isec Is Nothing Then
  795. arr(i, j) = j
  796. isec.CreateSelection
  797. isec.Delete
  798. End If
  799. Else
  800. arr(i, j) = j
  801. End If
  802. End If
  803. Next j
  804. Next i
  805. For i = 1 To gcnt
  806. arr = collect_arr(arr, i, i)
  807. Next i
  808. Set sr = ActiveSelectionRange
  809. For i = 1 To gcnt
  810. sr.RemoveAll
  811. inar = 0
  812. For j = 1 To gcnt
  813. If arr(i, j) > 0 Then
  814. sr.Add os.Shapes(j)
  815. inar = inar + 1
  816. End If
  817. Next j
  818. If inar > 1 Then
  819. If Group = "group" Then
  820. If shft < 4 Then sr_all.Add sr.Group
  821. End If
  822. Else
  823. If sr.Shapes.Count > 0 Then sr_all.AddRange sr
  824. End If
  825. Next i
  826. Set autogroup = sr_all
  827. End If
  828. ActiveDocument.EndCommandGroup
  829. Application.Optimization = False
  830. ActiveWindow.Refresh: Application.Refresh
  831. Exit Function
  832. errn:
  833. Application.Optimization = False
  834. End Function
  835. Public Function collect_arr(arr, ci, ki)
  836. lim = UBound(arr)
  837. For k = 1 To lim
  838. If arr(ki, k) > 0 Then
  839. arr(ci, k) = k
  840. If ki <> ci Then arr(ki, k) = Empty
  841. If ci <> k And ki <> k Then arr = collect_arr(arr, ci, k)
  842. End If
  843. Next k
  844. 'If ki <> ci Then arr(ki, ki) = Empty
  845. collect_arr = arr
  846. End Function
  847. '// 两个端点的坐标,为(x1,y1)和(x2,y2) 那么其角度a的tan值: tana=(y2-y1)/(x2-x1)
  848. '// 所以计算arctan(y2-y1)/(x2-x1), 得到其角度值a
  849. '// VB中用atn(), 返回值是弧度,需要 乘以 PI /180
  850. Private Function lineangle(x1, y1, x2, y2) As Double
  851. pi = 4 * VBA.Atn(1) '// 计算圆周率
  852. If x2 = x1 Then
  853. lineangle = 90: Exit Function
  854. End If
  855. lineangle = VBA.Atn((y2 - y1) / (x2 - x1)) / pi * 180
  856. End Function
  857. '// 角度转平
  858. Public Function Angle_to_Horizon()
  859. On Error GoTo ErrorHandler
  860. API.BeginOpt
  861. Set sr = ActiveSelectionRange
  862. Set nr = sr.LastShape.DisplayCurve.Nodes.all
  863. If nr.Count = 2 Then
  864. x1 = nr.FirstNode.PositionX: y1 = nr.FirstNode.PositionY
  865. x2 = nr.LastNode.PositionX: y2 = nr.LastNode.PositionY
  866. a = lineangle(x1, y1, x2, y2): sr.Rotate -a
  867. sr.LastShape.Delete '// 删除参考线
  868. End If
  869. ErrorHandler:
  870. API.EndOpt
  871. End Function
  872. '// 自动旋转角度
  873. Public Function Auto_Rotation_Angle()
  874. On Error GoTo ErrorHandler
  875. API.BeginOpt
  876. ' ActiveDocument.ReferencePoint = cdrCenter
  877. Set sr = ActiveSelectionRange
  878. Set nr = sr.LastShape.DisplayCurve.Nodes.all
  879. If nr.Count = 2 Then
  880. x1 = nr.FirstNode.PositionX: y1 = nr.FirstNode.PositionY
  881. x2 = nr.LastNode.PositionX: y2 = nr.LastNode.PositionY
  882. a = lineangle(x1, y1, x2, y2): sr.Rotate 90 + a
  883. sr.LastShape.Delete '// 删除参考线
  884. End If
  885. ErrorHandler:
  886. API.EndOpt
  887. End Function
  888. '// 交换对象
  889. Public Function Exchange_Object()
  890. Set sr = ActiveSelectionRange
  891. If sr.Count = 2 Then
  892. X = sr.LastShape.CenterX: Y = sr.LastShape.CenterY
  893. sr.LastShape.CenterX = sr.FirstShape.CenterX: sr.LastShape.CenterY = sr.FirstShape.CenterY
  894. sr.FirstShape.CenterX = X: sr.FirstShape.CenterY = Y
  895. End If
  896. End Function
  897. '// 参考线镜像
  898. Public Function Mirror_ByGuide()
  899. On Error GoTo ErrorHandler
  900. API.BeginOpt
  901. Set sr = ActiveSelectionRange
  902. Set nr = sr.LastShape.DisplayCurve.Nodes.all
  903. If nr.Count >= 2 Then
  904. byshape = False
  905. x1 = nr.FirstNode.PositionX: y1 = nr.FirstNode.PositionY
  906. x2 = nr.LastNode.PositionX: y2 = nr.LastNode.PositionY
  907. a = lineangle(x1, y1, x2, y2) '// 参考线和水平的夹角 a
  908. sr.remove sr.Count
  909. ang = 90 - a '// 镜像的旋转角度
  910. For Each s In sr
  911. With s
  912. .Duplicate '// 复制物件保留,然后按 x1,y1 点 旋转
  913. .RotationCenterX = x1
  914. .RotationCenterY = y1
  915. .Rotate ang
  916. If Not byshape Then
  917. lx = .LeftX
  918. .Stretch -1#, 1# '// 通过拉伸完成镜像
  919. .LeftX = lx
  920. .Move (x1 - .LeftX) * 2 - .SizeWidth, 0
  921. .RotationCenterX = x1 '// 之前因为镜像,旋转中心点反了,重置回来
  922. .RotationCenterY = y1
  923. .Rotate -ang
  924. End If
  925. .RotationCenterX = .CenterX '// 重置回旋转中心点为物件中心
  926. .RotationCenterY = .CenterY
  927. End With
  928. Next s
  929. End If
  930. ErrorHandler:
  931. API.EndOpt
  932. End Function
  933. '// 按面积排列计数
  934. Public Function Count_byArea(Space_Width As Double)
  935. If 0 = ActiveSelectionRange.Count Then Exit Function
  936. API.BeginOpt
  937. ActiveDocument.ReferencePoint = cdrCenter
  938. Set ssr = ActiveSelectionRange
  939. cnt = 1
  940. #If VBA7 Then
  941. ssr.Sort "@shape1.width * @shape1.height < @shape2.width * @shape2.height"
  942. #Else
  943. ' X4 不支持 ShapeRange.sort
  944. #End If
  945. Dim str As String, size As String
  946. For Each sh In ssr
  947. size = Int(sh.SizeWidth + 0.5) & "x" & Int(sh.SizeHeight + 0.5) & "mm"
  948. sh.SetSize Int(sh.SizeWidth + 0.5), Int(sh.SizeHeight + 0.5)
  949. str = str & size & vbNewLine
  950. Next sh
  951. ActiveDocument.ReferencePoint = cdrTopLeft
  952. For Each s In ssr
  953. If cnt > 1 Then s.SetPosition ssr(cnt - 1).LeftX, ssr(cnt - 1).BottomY - Space_Width
  954. cnt = cnt + 1
  955. Next s
  956. ' 写文件,可以EXCEL里统计
  957. ' Set fs = CreateObject("Scripting.FileSystemObject")
  958. ' Set f = fs.CreateTextFile("D:\size.txt", True)
  959. ' f.WriteLine str: f.Close
  960. str = Subtotals(str)
  961. Debug.Print str
  962. Dim s1 As Shape
  963. ' Set s1 = ActiveLayer.CreateParagraphText(0, 0, 100, 150, Str, Font:="华文中宋")
  964. X = ssr.FirstShape.LeftX - 100
  965. Y = ssr.FirstShape.TopY
  966. Set s1 = ActiveLayer.CreateParagraphText(X, Y, X + 90, Y - 150, str, Font:="华文中宋")
  967. API.EndOpt
  968. End Function
  969. '// 实现Excel里分类汇总功能
  970. Private Function Subtotals(str As String) As String
  971. Dim a, b, d, arr
  972. str = VBA.Replace(str, vbNewLine, " ")
  973. Do While InStr(str, " ")
  974. str = VBA.Replace(str, " ", " ")
  975. Loop
  976. arr = Split(str)
  977. Set d = CreateObject("Scripting.dictionary")
  978. For i = 0 To UBound(arr) - 1
  979. If d.Exists(arr(i)) = True Then
  980. d.Item(arr(i)) = d.Item(arr(i)) + 1
  981. Else
  982. d.Add arr(i), 1
  983. End If
  984. Next
  985. str = " 规 格" & vbTab & vbTab & vbTab & "数量" & vbNewLine
  986. a = d.keys: b = d.items
  987. For i = 0 To d.Count - 1
  988. ' Debug.Print a(i), b(i)
  989. str = str & a(i) & vbTab & vbTab & b(i) & "条" & vbNewLine
  990. Next
  991. Subtotals = str & "合计总量:" & vbTab & vbTab & vbTab & UBound(arr) & "条" & vbNewLine
  992. End Function