mikewolf2k 发表于 2018-8-22 14:50:51

zzyong00 发表于 2018-8-22 13:41
再来个稍差一点的,更差的,就不上了

这个会有什么问题?单元格内有两个text?这个不在此程序的处理范围内。

664571221 发表于 2018-8-23 09:22:47

代码如何使用

zzyong00 发表于 2018-8-23 12:34:26

有时候你很努力了,但就是不成功,为什么,可能原因就是方向错了!
如著名典故,南辕北辙.

zzyong00 发表于 2018-8-23 12:38:56

我十多年前就有类似的程序,还设置了容差对话框,但发现在实际使用时,问题太多了,才知道,当时的出发点就不对

mikewolf2k 发表于 2018-8-23 13:15:20

zzyong00 发表于 2018-8-23 12:38
我十多年前就有类似的程序,还设置了容差对话框,但发现在实际使用时,问题太多了,才知道,当时的出发点就 ...

能具体说说问题是什么么?表格太乱了?或者是多个text?我用坐标位置判断,对于基本规则的表格,没发现什么问题。如果表格实在太乱,那是制图人的制图太差,应该由制图人去改正。同样多个text也让制图改正。一个只有一个text并基本规范的表格,是对制图的基本要求,并且是可以实现的。
当然对于由于上下标导致多个text,我的具体应用中极少碰到,也就不考虑了。

qwh923820 发表于 2018-8-23 13:58:42

zzyong00 发表于 2018-8-23 12:38
我十多年前就有类似的程序,还设置了容差对话框,但发现在实际使用时,问题太多了,才知道,当时的出发点就 ...

又修修改改,那个上标次方实在搞不定,其他帮忙鉴定下,后面附上源码




Option Explicit

Public Sub Cad表格转Excel()
Dim objEntArr() As Object, i As Long
Dim objSset As AcadSelectionSet
Dim y As AcadSelectionSet
Dim pt1(2) As Double, pt2(2) As Double
Dim p, j, A(1 To 990, 1 To 7), B(), C(), D(), n, m, k, ky, kx, m1, m2, na$
Dim E()
'pt1,pt2是表格的位置,左下,右上
pt1(0) = -1500
pt1(1) = -1500
pt1(2) = 0
pt2(0) = 43200
pt2(1) = 43200
pt2(2) = 0
na = "QQQ"
k = 0
On Error Resume Next
If Not IsNull(ThisDrawing.SelectionSets.Item(na)) Then
    Set y = ThisDrawing.SelectionSets.Item(na)
    y.Delete
End If
Set y = ThisDrawing.SelectionSets.Add(na)
      Dim gpCode(0) As Integer
      Dim dataValue(0) As Variant
      gpCode(0) = 0
      dataValue(0) = "text,mtext"
      Dim groupCode As Variant, dataCode As Variant
      groupCode = gpCode
      dataCode = dataValue
'    pt1 = ThisDrawing.Utility.GetPoint(, "Enter a point: ")
'    pt2 = ThisDrawing.Utility.GetPoint(, "Enter a point: ")
y.Select acSelectionSetCrossing, pt1, pt2, groupCode, dataCode

    For i = 0 To y.Count - 1
      A(i + 1, 1) = i
      A(i + 1, 2) = y.Item(i).TextString
      p = y.Item(i).InsertionPoint
      k = IIf(y.Item(i).Height - k > 0, y.Item(i).Height, k)       'k是过滤间隙
      y.Item(i).GetBoundingBox m1, m2
      A(i + 1, 3) = p(0)
      A(i + 1, 4) = p(1)
      A(i + 1, 5) = (m1(0) + m2(0)) / 2          '文字中心坐标
      A(i + 1, 6) = (m2(0) - m1(0)) / 2          '文字长度的一半
      A(i + 1, 7) = (p(0) + A(i + 1, 5)) / 2   '插入点与文字中心坐标的中心点
    Next i
y.Delete
' Stop
'k = 50   'k是过滤间隙
ky = k
kx = k * 1.2
B = 过滤数组(A, 4, ky)
C = 过滤数组(A, 7, kx)
ReDim D(1 To UBound(B) + 1, 1 To UBound(C) + 1)
For i = 1 To UBound(A)
    If A(i, 2) = "" Then Exit For
    For n = 0 To UBound(B)
      '行的位置
      If Abs(B(n) - A(i, 4)) < ky Then
            Exit For
      End If
    Next n
    For m = 0 To UBound(B)
      '列的位置
      If Abs(C(m) - A(i, 7)) < kx Then
            Exit For
      End If
    Next m
    If D(UBound(B) + 1 - n, 1 + m) = "" Then
      D(UBound(B) + 1 - n, 1 + m) = i
    Else
      D(UBound(B) + 1 - n, 1 + m) = i & "~~" & D(UBound(B) + 1 - n, 1 + m)
    End If
Next i
E = 整合数组列(A, D, 1)
E = 替换文字内容(A, E)
Dim exlh As Object
Set exlh = GetObject(, "excel.application")
With exlh
    .workbooks(1).worksheets(1).Select
    .cells.Select
    .Selection.Clear
    '.cells(1, 1).resize(990, 7) = A
    '.cells(1, 9).resize(UBound(B) + 1, UBound(C) + 1) = D
    .cells(1, 1).resize(UBound(E), UBound(E, 2)) = E
   
End With
End Sub

Function 过滤数组(ByVal A, ByVal n, ByVal k) As Variant
'A是数组,n是过滤的列,k是过滤的间隙
Dim B(), i, j, p, m
j = 0
ReDim B(0)
B(0) = A(1, n)
For i = 2 To UBound(A)
    m = 0
    If A(i, n) = "" Then Exit For
    For p = 0 To j
      If Abs(A(i, n) - B(p)) < k Then
            m = 1
            Exit For
      End If
    Next p
    If m = 0 Then
      j = j + 1
      ReDim Preserve B(j)
      B(j) = A(i, n)
    End If
Next i
过滤数组 = 冒泡排序(B)
End Function
Function 冒泡排序(ByVal A) As Variant
'从小到大
Dim i, j, n
For i = 0 To UBound(A) - 1
    For j = 0 To UBound(A) - 1 - i
      If A(j) > A(j + 1) Then
            n = A(j + 1)
            A(j + 1) = A(j)
            A(j) = n
      End If
    Next j
Next i
冒泡排序 = A
End Function
Function 整合数组列(ByVal A, ByVal D, ByVal n)
'以中心点和插入点间距为判断
'当相连两列n列与n+1列比较,n+1列文字插入点或中心点在n列的插入点与中心点之间时,合并
'n列的插入点与中心点之间距离取该列最大值
Dim i, j, L, p, q, x1, x2, y, B, x3, x4
Dim C()
L = 0
If n >= UBound(D, 2) Then
    整合数组列 = D
    Exit Function
End If
'n列的插入点与中心点之间距离取该列最大值L及插入点和中心点X坐标
For i = 1 To UBound(D)
    If D(i, n) <> "" Then
      If InStr(D(i, n), "~~") > 0 Then
            B = Split(D(i, n), "~~")
            For j = 0 To UBound(B)
                y = Abs(A(B(j), 5) - A(B(j), 3))
                If L > y Then
                  L = y
                  x1 = A(B(j), 3): x2 = A(B(j), 5)
                End If
            Next j
            Erase B
      Else
            y = Abs(A(D(i, n), 5) - A(D(i, n), 3))
            If L < y Then
                L = y
                x1 = A(D(i, n), 3): x2 = A(D(i, n), 5)
            End If
      End If
    End If
Next i
'Stop
For i = 1 To UBound(D)
p = 0
    If D(i, n + 1) <> "" Then
      If InStr(D(i, n + 1), "~~") > 0 Then
            B = Split(D(i, n + 1), "~~")
            For j = 0 To UBound(B)
                x3 = A(B(j), 3): x4 = A(B(j), 5)
                If IIf(x3 > x4, x4, x3) < IIf(x2 > x1, x2, x1) Then
                  p = 1
                  Exit For
                End If
            Next j
            Erase B
      Else
            x3 = A(D(i, n + 1), 3): x4 = A(D(i, n + 1), 5)
            If IIf(x3 > x4, x4, x3) < IIf(x2 > x1, x2, x1) Then p = 1
      End If
      If p = 1 Then
            If D(i, n) = "" Then
                D(i, n) = D(i, n + 1)
            Else
                D(i, n) = 纵向排列同一单元格文字(A, D(i, n) & "~~" & D(i, n + 1))
            End If
            D(i, n + 1) = ""
      End If
    End If
Next i
C = 去除数组第N列空列(D, n + 1)
If UBound(C, 2) < UBound(D, 2) Then n = n - 1
整合数组列 = 整合数组列(A, C, n + 1)
End Function
Function 纵向排列同一单元格文字(ByVal A, ByVal t)
Dim B, i, j, k, C(), D(), E()
B = Split(t, "~~")
k = ""
ReDim C(UBound(B))
ReDim E(0 To UBound(B), 1 To 2)
For i = 0 To UBound(C)
    C(i) = A(B(i), 4)
    E(i, 1) = C(i)
    E(i, 2) = B(i)
Next i
Erase B
D = 冒泡排序(C)
For i = UBound(D) To 0 Step -1
    For j = 0 To UBound(D)
      If Abs(D(i) - E(j, 1)) < 0.001 Then
            If k = "" Then
                k = E(j, 2)
            Else
                k = k & "~~" & E(j, 2)
            End If
            E(j, 1) = -1235.778
      End If
    Next j
Next i
纵向排列同一单元格文字 = k
End Function
Function 去除数组第N列空列(ByVal D, ByVal n)
Dim B(), i, j
For i = 1 To UBound(D)
    If D(i, n) <> "" Then 去除数组第N列空列 = D: Exit Function
Next i
ReDim C(1 To UBound(D), 1 To UBound(D, 2) - 1)
For i = 1 To UBound(D)
    For j = 1 To UBound(C, 2)
      If j < n Then
            C(i, j) = D(i, j)
      ElseIf j >= n Then
            C(i, j) = D(i, j + 1)
      End If
    Next j
Next i
去除数组第N列空列 = C
End Function
Function 替换文字内容(ByVal A, ByVal D)
Dim B, i, j, k, n, m
For i = 1 To UBound(D)
    For j = 1 To UBound(D, 2)
      m = ""
      If D(i, j) <> "" Then
            If InStr(D(i, j), "~~") > 0 Then
                B = Split(D(i, j), "~~")
                For k = 0 To UBound(B)
                  If m = "" Then m = A(B(k), 2) Else m = m & Chr(10) & A(B(k), 2)
                Next k
                Erase B
            Else
                m = A(D(i, j), 2)
            End If
            D(i, j) = m
      End If
    Next j
Next i
替换文字内容 = D
End Function




qwh923820 发表于 2018-8-23 14:14:07

664571221 发表于 2018-8-23 09:22
代码如何使用

1.制定要转换的CAD表格位置,如果你想改成插件用,可以采用getpoint方法(就是注释掉的),如果你是写在批量操作的程序里面,每次把PT1,PT2的值传入一遍。


2、根据实际情况选择允许同行同列偏移位置误差,默认k是文字高度,ky是行偏移误差。kx是列偏移误差,可以根据实际情况进行调整


3、输出位置自行修改,你想要输出装excel那个位置,自行修改,并且去掉.selection.clear这句,不然全清空了

snight523 发表于 2018-8-23 15:46:12

小白 不会用 平时都是用些lsp程序。大佬们能不能讲下要怎么使用?

mikewolf2k 发表于 2018-8-23 16:01:10

如何判断是同一个单元格的?代码看起来太累,能说说么。粗略扫了一下,似乎是如果XY在前后行列的值之间,就被认为是合并的,感觉你的判断依据很依赖表格的样式,如果某行或者某列全空,仅有中间一个格子有内容,是不是会被合并到其它行列了?
另外关于后面这个例子,实际上的工作流程应该是excel里填好,然后再生成dwg,顺序反了哈。

qwh923820 发表于 2018-8-23 16:40:56

mikewolf2k 发表于 2018-8-23 16:01
如何判断是同一个单元格的?代码看起来太累,能说说么。粗略扫了一下,似乎是如果XY在前后行列的值之间,就 ...

是的,先如果某行某列全空,是被删除掉的。如果要精准判断,后续可以加入线条的坐标进行定位判断。
本程序流程
页: 1 [2] 3 4 5 6
查看完整版本: 分享一个自己CAD表格转EXCEL源程序