1
1

Tools.bas 31 KB

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