panliang9 发表于 2024-3-26 20:31:50

两份图纸块同步,G版的思路

本帖最后由 panliang9 于 2024-4-12 13:35 编辑

两份图纸,都处于打开的状态,如何让图块同步。

在这个贴子里,G版提供的代码,可以在A图中,插入B图,但是A图中的图块按B图的更新。

http://bbs.mjtd.com/forum.php?mod=viewthread&tid=100770&page=1#pid579132

略微更改后,得到下面这个代码,这个代码中固定指向了一个固定的文件“D:\投影图\000.DWG”,执行代码后,就按照指定的文件“D:\投影图\000.DWG”更新本图的块。

现在的问题是,指定的文件必须是关闭的状态,如果是打开的,就不能更新。

现在想知道,有没有办法,同时打开的两份图纸A和B,用一个指令,可以让A图根据B图中的图块更新,同理,也可以让B图中根据A图中的同名图块更新。

我把A图依据B图更新图块的程序贴在下面,看大家有没有办法解决必须关闭文件才能更新这个问题。(奇怪,没法传附件,是怎么回事)


;; 自动更新本图的图块,不插入文件 base By Gu_xl
(defun c:es (/ DWGNAME DBXDOC ACVER DBXMODELSPACE BLOCKS DOC DBXBLOCKNAMES OBJS)
(setq DwgName "D:\\投影图\\000.DWG") ; 直接指定文件路径
(setq
    DBXDOC (vla-GetInterfaceObject
             (vlax-get-acad-object)
             (if (< (setq acVer (atoi (getvar "ACADVER"))) 16)
               "ObjectDBX.AxDbDocument"
               (strcat "ObjectDBX.AxDbDocument." (itoa acVer))
             )
         )
)
(vla-open DBXDOC DWGNAME)
(setq DBXModelSpace (vla-get-ModelSpace DBXDOC))
(setq blocks (vla-get-blocks
               (setq doc (vla-get-ActiveDocument (vlax-get-acad-object)))
               )
)
(vlax-for blk (vla-get-blocks DBXDOC)
    (if (not (or (eq :vlax-true (vla-get-isXRef blk))
               (eq :vlax-true (vla-get-isLayout blk))
               (= "*U" (substr (vla-get-name blk) 1 2))
               (= "*D" (substr (vla-get-name blk) 1 2))
               (= "*T" (substr (vla-get-name blk) 1 2))
                )
         )
      (setq dbxblocknames (cons (vla-get-name blk) dbxblocknames))
    )
)
(setq dbxblocknames
         (vl-remove-if-not
         '(lambda (x) (TBLSEARCH "BLOCK" x))
         dbxblocknames
         )
)
(if dbxblocknames
    (progn
      (foreach block dbxblocknames
      (vlax-for obj (vla-item blocks block)
          (vla-delete obj)
      )
      (setq objs nil)
      (vlax-invoke
          dbxDoc
          'CopyObjects
          (vlax-for a
            (vla-item (vla-get-blocks DBXDOC) block)
            (setq objs (cons a objs))
          )
          (vla-item blocks block)
      )
      )
      (vla-regen doc :vlax-true)
      (prompt (strcat "\n更新了" (itoa (length dbxblocknames)) "个图块!"))
    )
    (prompt "\n没有可更新的图块!")
)
(vlax-release-object DBXDOC)
(princ)
)

现在变通的解决方案是。
1、A图(很复杂的大图)
2、B图,临时用图,用来改A图上的块。
3、C图,用来保存需要更新的图,例如上面代码中的 “D:\投影图\000.DWG”

工作方法,永远不在复杂的A图上改块,速度慢。把A图中的块复制出来放到B图,B图改好后另存为C图,然后A图根据C图更新块。

下面是把B图另存为C的代码。

(defun c:ge (/ dwgname filedia cmddia)
;; 保存当前FILEDIA和CMDDIA的设置
(setq filedia (getvar "FILEDIA"))
(setq cmddia (getvar "CMDDIA"))

;; 关闭文件对话框和命令对话框
(setvar "FILEDIA" 0)
(setvar "CMDDIA" 0)

;; 设置新文件名
(setq dwgname "D:\\投影图\\000.DWG")

;; 执行写块命令
(command "_.wblock" dwgname "y" "*")

;; 恢复FILEDIA和CMDDIA的设置
(setvar "FILEDIA" filedia)
(setvar "CMDDIA" cmddia)

;; 提示用户
(princ "\n当前图形已另存为D:\\投影图\\000.DWG,但未打开。")
(princ)
)

你有种再说一遍 发表于 2024-3-26 21:22:04

本帖最后由 你有种再说一遍 于 2024-3-27 01:18 编辑

换个语言,然后你就知道跨图纸跨线程跨进程多好做了...
思路就是遍历图A块表产生一份hashmap,然后去和图B比较,
名称冲突的就深度克隆过去,覆盖模式.
再监控文档的图元改变事件,改块并冲突就深度克隆过去.
删除块呢?摇摇头.
...
块表本身就能索引的,我因为cad08索引功能出错(能够获取entity.isErase==true)才遍历构造hashmap...


lisp跨文档需要骚技巧,通讯也是...所以你会发现怎么难以直接控制下一份图的事件呢...

lxl217114 发表于 2024-3-26 21:34:21

调用设计中心,重定义一下是否可行?

panliang9 发表于 2024-3-27 08:34:06

lxl217114 发表于 2024-3-26 21:34
调用设计中心,重定义一下是否可行?
没看到有调用设计中心的例子。

G版的程序可以实现更新,但必须文件处于关闭状态,好象不关闭就无法访问数据库,一个变通的办法应该是将要访问的文件,另存为一个临时文件,然后访问这个临时文件,执行完毕后把这个临时文件删掉。

“lxl217114” 长老能不能出手尝试一下,大家走过路过的,希望都尝试一下。

lxl217114 发表于 2024-3-27 11:22:24

panliang9 发表于 2024-3-27 08:34
lxl217114 发表于 2024-3-26 21:34
调用设计中心,重定义一下是否可行?
没看到有调用设计中心的例子。


从来没写过lsp代码,实在没这个能力。一直想学习写,但是还没开始。

weimeng555 发表于 2024-4-3 00:22:22

这个东西不错,最好是能再支持属性块、动态块,这样就可以放心的修改动态块了
页: [1]
查看完整版本: 两份图纸块同步,G版的思路