拋磚引玉 之 VISIO VBA 繪制鏈表

“學(xué)習(xí)永遠(yuǎn)是個痛苦的過程懊昨,需要極大的勇氣才能持之以恒”

1. 動機(jī)

似乎是十年之前窄潭,在得到一本圖書的掃描版pdf后,由于非常喜歡該圖書酵颁,所以進(jìn)行了“重新編輯”(只是留給自己看嫉你,從未散播過給他人)。該圖書主要是“圖文配合”躏惋,且是以圖為主的一本書幽污。因此,在編輯過程中簿姨,需要將pdf中的圖片復(fù)制并粘貼到word中距误,并且需要根據(jù)我自己的排版調(diào)整大小簸搞。由于該圖書的圖片特別多,近2000多張圖片的樣子准潭,在調(diào)整了100張圖片后果斷放棄手工調(diào)整圖片大小的方式趁俊,太受罪了。于是想起使用宏來處理刑然,完全可以選擇圖片后錄制宏來幫我完成寺擂,但是這樣也得一張張?zhí)幚恚€是麻煩闰集。因此沽讹,第一次“鼓起勇氣”拿起VBA這個神器來。雖然之前沒有學(xué)過任何VB的內(nèi)容(就是懶武鲁,不愿意學(xué))爽雄,但在搜索+嘗試的基礎(chǔ)上20分鐘的樣子搞定了一個VBA程序,運行后幾秒就完成了剩余圖片的大小調(diào)整沐鼠,完美完成任務(wù)挚瘟。這樣,第一次體會到VBA的好處饲梭。雖然是有好處乘盖,但咱也不做編輯,so憔涉,之后再也沒有用過VBA订框。雖然MS的OFFICE功能超強(qiáng),但畢竟“學(xué)習(xí)永遠(yuǎn)是個痛苦的過程”兜叨,還是能不學(xué)就不學(xué)吧(懶是一種態(tài)度)穿扳。這里吐槽一下,有專門的“人才”跑學(xué)校來講LATEX国旷,說其功能如何強(qiáng)大矛物,且曰Word完成不了的LATEX可以。我只想說跪但,那是您真·不會使Word履羞。這么好的所見即所得(WYSIWYG)工具為啥不好好用,干嘛給自己找別扭屡久?推薦侯捷老師的書《Word排版藝術(shù)》忆首,針對Word2003的,但是里面的內(nèi)容即使2019也足夠你使用了被环,并且還有VBA這一神器糙及。

寫了那么多,下面進(jìn)入正題蛤售。

由于各種原因丁鹉,經(jīng)常要將某種的數(shù)據(jù)結(jié)構(gòu)展示為圖型妒潭,特別是圖啊,樹啊什么的揣钦,每次雖然拿VISIO繪制也不算太麻煩雳灾,但是畢竟還得一個一個的繪制出來,于是就想能不能編制程序冯凹,通過讀取文件的形式將想繪制的圖形繪制出來谎亩。雖然自己編程可以實現(xiàn),但是自己編的程序宇姚,繪制出來的圖形可能將會比較粗糙匈庭,要想美觀,需要下一定的功夫才行浑劳,本來就是為了方便(懶)嘛阱持。并且繪制的圖形希望可以進(jìn)行二次編輯和調(diào)整,如果這樣的功能全都由自己實現(xiàn)的話魔熏,光各種Style的設(shè)置就麻煩死了衷咽,畢竟咱不專業(yè)啊。于是就想蒜绽,能不能用VBA直接在VISIO中繪制镶骗,這樣繪制出的圖形可以只是一個基本結(jié)構(gòu),美觀的話可以繼續(xù)進(jìn)行手工調(diào)整躲雅,這樣多省事兒鼎姊,于是就有了本文所涉內(nèi)容。

圖 1就是通過VBA在VISIO繪制的相赁,完全符合自己的要求相寇,想上色上色,想修改修改噪生,完全支持二次手工加工裆赵。下文就拿它的繪制作為“磚”东囚,拋來引“玉”跺嗽。

圖1 鏈表.jpg

不過,對于沒有VB基礎(chǔ)的人來說页藻,想完成這樣的繪制桨嫁,也還是有點麻煩的——需要熟悉熟悉VB的文法。當(dāng)然這都不是關(guān)鍵點份帐,關(guān)鍵點是MS給出的VISIO相關(guān)的VBA文檔璃吧,感覺簡直就是不想讓人看懂,很敷衍的樣子(也可能是自己膚淺了)废境。另外畜挨,網(wǎng)上的相關(guān)資料不能說少筒繁,但是很散。因此巴元,個人自我感覺這塊磚毡咏,還是得拋的。

2. 基本概念

下面先介紹一下針對Visio進(jìn)行VBA編程中所需要了解的一些基本對象和概念逮刨。說實話呕缭,弄清楚下面這些對象究竟是啥含義還真是挺費事兒。特別地修己,微軟提供的在線文檔恢总,如果在不了解這些概念前看簡直就是天書,會感覺寫的很抽象睬愤,但是片仿,在了解這些概念后就好很多,起碼知道在說啥尤辱,并且會發(fā)現(xiàn)理解起來也比較容易了滋戳。當(dāng)然,本來幫助文檔應(yīng)該是給不熟悉的人看的啥刻,但結(jié)果是讓不熟悉的人看著一頭霧水奸鸯,那么本身本質(zhì)上還是文檔的撰寫者寫的不合格。別跟我抬杠可帽,很多文檔的編輯者都有這樣的問題娄涩,我也不一定例外。那么來看下面的基礎(chǔ)概念:

  1. Page:頁面對象映跟,承載各種繪制元素的頁面蓄拣,包括前景和背景頁面。ActivePage努隙,激活頁面球恤,正在繪制圖新的當(dāng)前頁面。
  2. Stencil:模具荸镊,Master的一個集合咽斧,可以自己創(chuàng)建模具,包含自己所需的各種Master躬存。
  3. Master:原件张惹,是模具中的一個對象。
  4. Shape:圖形岭洲,在繪畫頁面中繪制的對象宛逗,一般通過從Stencil中拖拽一個Master對象,并放置到繪畫頁面上實現(xiàn)創(chuàng)建盾剩。
  5. Document Stencil:文檔模具雷激,一個特殊的Stencil替蔬,它里面存放的是從Stencil中拖到繪畫頁面中的Shape所用的那些Master的副本。請注意這里的Master不是直接引用屎暇,是copy进栽,但如果你創(chuàng)建的多個Shape是來自同一個Master,那么Document Stencil中則不重新創(chuàng)建新的同樣的Master恭垦,除非你之前修改了那個被copy的Master快毛。這樣做有什么好處呢?好處是番挺,如果你想修改繪制頁面中的現(xiàn)有的由相同的Master創(chuàng)建的所有Shape的style唠帝,那么你只要修改Document Stencil中的這個Master就能夠?qū)崿F(xiàn)全部修改。但你如果修改的是Stencil中的Master玄柏,則當(dāng)前繪畫頁面中之前是由拖拽這個Master實現(xiàn)繪制的那些Shape不會進(jìn)行修改襟衰。
圖2 VISIO對象說明.jpg
  1. Section:部分,1個Shape的Section包括多個Row和Cell粪摘,對應(yīng)存儲該Shape再某方面的特征屬性瀑晒,如文字部分的特征屬性集合,線條屬性集合等徘意。Shape的每個Section的具體內(nèi)容可以在點擊Visio“開發(fā)工具”菜單下的“ShapeSheet”按鈕后彈出的窗口中查看苔悦。每個Shape均有多個Section,每個Section中均包括若干的Row椎咧,每個Row中有若干Cell玖详。
  2. Row:行,Section的組成部分勤讽,每個Section可以有一到多個Row蟋座,每一行就是一個Row。
  3. Cell:格子脚牍,Shape向臀,Style,或者Row對象的屬性(之一)诸狭。如券膀,Shape的每個Section中的每個Row中包括多個Cell,也就是說其中的一個Cell表示該Shape的在某Section下的某Row中的某個屬性作谚。
圖3 Document Stencil和Shape Sheet顯示按鈕.jpg
圖4 Shape Sheet中的Row和Cell.jpg

具體各個概念可以見圖 2三娩、圖 3和圖 4中的標(biāo)注庵芭。還有其他的相關(guān)概念妹懒,如Selection等,這里不介紹双吆,在后面隨著使用會具體說明眨唬。特別地会前,圖4中的ShapeSheet對應(yīng)的Shape是ActivePage中被選中的“三角形”Shape,相應(yīng)的Row和Cell也是這個“三角形”的匾竿。通過這次研究Visio VBA才發(fā)現(xiàn)人家軟件的強(qiáng)大瓦宜,真要是自己開發(fā)滿足之前所述需求的軟件,那會累死的岭妖。

3. 繪制設(shè)計

本文的樣例是一個鏈表(List)临庇,包括頭結(jié)點(HD),和鏈表中的各結(jié)點(Ai昵慌,i∈[1,n])假夺,見圖 1所示。為了簡化問題斋攀,本文的鏈表就是由相同的結(jié)點(Node)構(gòu)成已卷,不單設(shè)頭結(jié)點的數(shù)據(jù)結(jié)構(gòu),和鏈表結(jié)點的數(shù)據(jù)結(jié)構(gòu)淳蔼,以及表示鏈表的List結(jié)構(gòu)(沒學(xué)好數(shù)據(jù)結(jié)構(gòu)的請回爐重鑄)侧蘸。因此,首先應(yīng)該定義鏈表結(jié)點的類型鹉梨。另外讳癌,本人VB不靈,屬于現(xiàn)學(xué)現(xiàn)賣存皂,所以不要在這方面來較真兒析桥,且以后不在聲明。

Type ELEMENT_NODE_Shapes
    InforShape As Visio.Shape
    PointerShape As Visio.Shape
End Type

ELEMENT_NODE_Shapes是定義的鏈表結(jié)點對象類型艰垂,其中包括數(shù)據(jù)域InforShape和指針域PointerShape泡仗,它們都是Visio.Shape類型對象,也就是上文中的Shape類型對象猜憎。這樣就能夠之后在其基礎(chǔ)上繪制出兩個連續(xù)的shape(矩形)來表示鏈表結(jié)點娩怎,見圖 5,第1給矩形為數(shù)據(jù)域胰柑,第2個矩形為指針域截亦。

圖5 繪制出的鏈表結(jié)點.jpg

首先,是DrawList過程柬讨。DrawList為主控程序崩瓤,用于繪制鏈表,其中CreateNode用于在指定位置創(chuàng)建鏈表結(jié)點的Shape踩官,ConnectTwoNode用“連線”Shape連接創(chuàng)建的兩個鏈表Shape却桶。簡要說明VB中Sub和Function的區(qū)別:Sub就是表示過程,無返回值;Function是有返回值的颖系,具體請參考VB相關(guān)資料嗅剖。另外,需要注意的是Visio的頁面的坐標(biāo)和平常熟悉的Windows坐標(biāo)不太一樣嘁扼,Windows的坐標(biāo)是左上角為<0, 0>信粮,但是Visio中式左下角為<0, 0>。本文的Visio文檔是使用美制單位(英寸)趁啸,所以1個單位長度就是1英寸强缘。PosX和PosY分別對應(yīng)一個Shape對象的繪制位置,即圖形外框的中心點(三角形Shape的外框也是矩形的)不傅。
注意:在簡書的代碼編輯系統(tǒng)中欺旧,不認(rèn)VB的注釋,所以前面加了//蛤签,如果你copy 的話辞友,請恢復(fù)。

Sub DrawList()
    Dim Delta As Double
    //' 增量震肮,1.25個單位称龙,本文是英寸
    Delta = 1.25 
    Dim PosX As Double
    Dim PosY As Double
    PosX = 0.5  //' 圖形繪制X坐標(biāo)
    PosY = 10  //' 圖形繪制Y坐標(biāo)
    //' 頭結(jié)點用于頭結(jié)點的處理
    Dim HeadNode As ELEMENT_NODE_Shapes
    //' 通過CreateNode在指定的位置創(chuàng)建頭結(jié)點,并指定頭結(jié)點的數(shù)據(jù)域顯示的字符串
    HeadNode = CreateNode(PosX, PosY, "HD")
    //' 定義結(jié)點數(shù)組
    Dim Node(100) As ELEMENT_NODE_Shapes
    //' PrevNode用于之后的鏈表連續(xù)處理
    Dim PrevNode As ELEMENT_NODE_Shapes
    PrevNode = HeadNode
    //'連續(xù)創(chuàng)建10個結(jié)點戳晌,并且用ConnectTwoNode實現(xiàn)結(jié)點Shape的連線(帶箭頭的線)
    For Index = 1 To 10
        PosX = PosX + Delta //'橫坐標(biāo)每次遞增Delta
        //' 鏈表終結(jié)點Shape數(shù)據(jù)域顯示的文字是A和index湊成的字符串鲫尊,如A5
        Node(Index - 1) = CreateNode((PosX), PosY, "A" & Index)
        //' 每次將PrevNode和當(dāng)前新創(chuàng)建的結(jié)點進(jìn)行連線
        Call ConnectTwoNode(PrevNode, Node(Index - 1))
        PrevNode = Node(Index - 1) //' PrevNode綁定到新創(chuàng)建的結(jié)點上,以便后繼處理
        //' 圖形繪制Y坐標(biāo)的控制沦偎,達(dá)到一定程度就“換行”
        If Index Mod 5 = 0 Then
            PosX = 0.5
            PosY = PosY - 1
        End If
    Next
End Sub

其次疫向,是CreateNode方法,用于在start_x和start_y位置繪制創(chuàng)建的Node并返回創(chuàng)建的Node豪嚎,該Node的數(shù)據(jù)域顯示的是由info傳入的String搔驼。其中需要說明的內(nèi)容有:

  1. ActivePage.Drop,該方法將指定的Stencil中的Master對象繪制到頁面中侈询。
  2. 通過Application.Documents.Item指定想要的Stencil舌涨,如本文使用的“BASIC_M.vssx”(“基本形狀”)。至于具體如何知道那個Stencil叫啥名字扔字,本人也沒有太好的辦法囊嘉,目前采用就是通過錄制宏的形式,拖動一個想要的Stencil中的Master革为,來查看錄制好的宏代碼中的Stencil和Master的名稱扭粱。特別是本人使用的是中文版的Visio≌痖荩看看以后有沒有啥好方法琢蛤,您如果知道請不吝賜教!
  3. 設(shè)置一個繪制好的Shape的文字的字體大小需要訪問該Shape對應(yīng)的Characters的Section中的Row的存儲字體配置的Cell。下面TempNode.InforShape虐块,就是結(jié)點的數(shù)據(jù)域?qū)?yīng)的Shape俩滥,其通過.Characters獲得對應(yīng)的字符Section屬性對象,并通過.CharProps屬性嘉蕾,指定visCharacterSize參數(shù)獲得字符Size的屬性贺奠,并設(shè)置為14pt,見圖 6错忱,紅框中是該Shape的Character Section儡率,藍(lán)框中的是對應(yīng)Size的Cell。其中visCharacterSize是一個枚舉量以清,其值為7儿普,你寫7其實也是可以的,具體可以參考MS文檔:https://docs.microsoft.com/en-us/office/vba/api/visio.characters.charprops掷倔,建議有條件的話眉孩,還是看英文的文檔。另外勒葱,Cell有不同的訪問方式浪汪,如:可以通過Shape對象的CellsSRC方法訪問。
圖6 Character Section和Size Cell.jpg
  1. 可以通過Shape.CellsSRC屬性來訪問一個Shape的某Section下的某Row中的某Cell凛虽,要么怎么名字中有SRC死遭,具體可以參考MS文檔:https://docs.microsoft.com/en-us/office/vba/api/visio.shape.cellssrc。每個Shape都有一個ShapeSheet凯旋,這個就相當(dāng)于一個三維表呀潭,那么通過第1個參確定要訪問的Section,第2個參數(shù)指定確定的Section中要訪問的Row至非,第3個參數(shù)指定該Row中的Cell钠署。在沒有了解SheetShape的作用之前,看MS提供的文檔真是要命荒椭,根本不知道他們在說啥踏幻,費事兒就費事兒在這里了。
  2. Section戳杀、Row该面、Cell的枚舉量的定義,請參考MS的這3篇文檔信卡,有了它你就能夠拿到Shape中的任何你想要的Cell:
    a) https://docs.microsoft.com/en-us/office/vba/api/visio.vissectionindices
    b) https://docs.microsoft.com/en-us/office/vba/api/visio.visrowindices
    c) https://docs.microsoft.com/en-us/office/vba/api/visio.viscellindices
  3. 獲得了Cell隔缀,通過設(shè)置Formula,類似于Excel中的每個方格cell傍菇,ShapeSheet里面每個Cell都可以使用公式來完成屬性的設(shè)置猾瘸,這點不得不佩服MS的強(qiáng)大,能夠左到不同工具的統(tǒng)一的處理(好像也就應(yīng)該這么做才更合理)。
  4. 組合繪制好的數(shù)據(jù)域和指針域的Shape牵触。組合是先建立選擇Selection對象淮悼,然后選擇各個Shape,然后調(diào)用Selection對象的Group方法將已經(jīng)選定的各個圖形進(jìn)行組合揽思。需要說明一下袜腥,選擇第一個Shape時,需要保證沒有選擇其他的Shape钉汗,因此羹令,Select方法的的選擇動作參數(shù)(第2個參數(shù))要綁定visDeselectAll 和 visSelect,表示先全不選然后選擇該Shape损痰。
Function CreateNode(start_x As Double, start_y As Double, info As String) As ELEMENT_NODE_Shapes
    Dim TempNode As ELEMENT_NODE_Shapes
    Set TempNode.InforShape =
    //' 在當(dāng)前頁面Drop一個矩形到指定位置福侈,該矩形由BASIC_M.vssx這個Stencil里面的矩形Master得到
    ActivePage.Drop(Application.Documents.Item("BASIC_M.vssx").Masters.ItemU("Rectangle"), start_x, start_y)
    TempNode.InforShape.Text = info //' 設(shè)置該矩形的文字信息為參數(shù)info的內(nèi)容
    //' 設(shè)置該Shape的字符size的屬性
    TempNode.InforShape.Characters.CharProps(visCharacterSize) = 14
    //' 繪制指針域的Shape,橫移0.5個單位長度
    Set TempNode.PointerShape = ActivePage.Drop(Application.Documents.Item("BASIC_M.vssx").Masters.ItemU("Rectangle"), start_x + 0.5, start_y)
    //' 聲明一個Cell變量卢未,用于之后訪問不同的Cell
    Dim TempCell As Visio.Cell
    //' 設(shè)置繪制矩形(數(shù)據(jù)域和指針域)的透明度為0.8(80%的透明度)
    Set TempCell = TempNode.InforShape.CellsSRC(visSectionObject, visRowFill, visFillForegndTrans)
    TempCell.Formula = "0.8"
    Set TempCell = TempNode.PointerShape.CellsSRC(visSectionObject, visRowFill, visFillForegndTrans)
    TempCell.Formula = "0.8"
    //' 設(shè)置繪制矩形(數(shù)據(jù)域和指針域)的寬和長肪凛,均為0.5英寸
    Set TempCell = TempNode.InforShape.CellsSRC(visSectionObject, visRowXFormOut, visXFormWidth)
    TempCell.Formula = "0.5"
    Set TempCell = TempNode.InforShape.CellsSRC(visSectionObject, visRowXFormOut, visXFormHeight)
    TempCell.Formula = "0.5"
    Set TempCell = TempNode.PointerShape.CellsSRC(visSectionObject, visRowXFormOut, visXFormWidth)
    TempCell.Formula = "0.5"
    Set TempCell = TempNode.PointerShape.CellsSRC(visSectionObject, visRowXFormOut, visXFormHeight)
    TempCell.Formula = "0.5"
    //' 下面要進(jìn)行組合,所以聲明一個選擇對象的變量
    Dim Selection As Visio.Selection
    //' 設(shè)置為激活窗口的選擇
    Set Selection = ActiveWindow.Selection
    //' 選擇數(shù)據(jù)域的矩形Shape辽社,并且先全部去掉選擇伟墙,然后再選擇,防止選取了其他的Shape
    Selection.Select TempNode.InforShape, visDeselectAll + visSelect
    //' 然后再選擇指針域的矩形Shape
    Selection.Select TempNode.PointerShape, visSelect
    //' 申明一個Shape變量爹袁,之后綁定組合后的對象
    Dim GroupShape As Visio.Shape
    //' 將之前選擇的Shape進(jìn)行組合远荠,組合的結(jié)果綁定到GroupShape上
    Set GroupShape = Selection.Group
    //' 返回的是創(chuàng)建的TempNode,也就是鏈表結(jié)點結(jié)構(gòu)的對象失息,而不是Group之后的對象譬淳,因為之后指針域的Shape需要進(jìn)行連線到后一個結(jié)點的數(shù)據(jù)域?qū)ο笊?    CreateNode = TempNode
End Function

再次,ConnectTwoNode使用一個連接線(帶箭頭)連接兩個Node的對應(yīng)Shape盹兢,前一個Node的指針域Shape的X2連接點作為起點邻梆,后一個Node的數(shù)據(jù)域Shape的X4連接點的作為終點。其中绎秒,需要說明的有:

  1. 連接線浦妄,本文里面選擇的是動態(tài)連接線,就是開始菜單下的“連接線”(一般在“指針工具”下方)见芹,因為其可以根據(jù)連接的兩個Shape之間的相對位置會“動態(tài)”調(diào)整線條布局剂娄。也可以根據(jù)需求選擇調(diào)用Shape的一些圖形繪制方法去創(chuàng)建,如:DrawArcByThreePoints玄呛,DrawLine等阅懦。
  2. 動態(tài)連接線默認(rèn)沒有箭頭,需要進(jìn)行設(shè)置徘铝,通過CellsSRC方法可以獲的連接線對應(yīng)的屬性的Cell耳胎,通過設(shè)置屬性值改變該屬性惯吕。
  3. 連接Shape,先獲得連接線的起點Cell和終點Cell怕午,將使用起點Cell和終點Cell的的GlutTo方法废登,分別連接到不同Shape的連接點(Connection Point)上。
  4. 不同類型的Shape郁惜,會有不同數(shù)量的Connection Point堡距,如:三角形有四個,分別是三個頂點和中間的扳炬,名稱分別是Connection.X1~ Connection.X4(名稱缺省不顯示吏颖,見紅框左側(cè)搔体,但可以選擇一個后點擊其他灰色框的觀察其缺省名稱)恨樟,具體的情況可以通過觀察該Shape的SheetShape進(jìn)行確定,見圖 7所示疚俱。
圖7 三角形的連接點.jpg
//' 使用動態(tài)連線劝术,連接2個鏈表結(jié)點Node中的指針域和數(shù)據(jù)域的Shape
Sub ConnectTwoNode(PrevNode As ELEMENT_NODE_Shapes, NextNode As ELEMENT_NODE_Shapes)
    //' 聲明并獲取“動態(tài)連線”的Shape
    Dim Line As Visio.Shape
    Set Line = ActivePage.Drop(ActiveDocument.Masters.ItemU("Dynamic connector"), 1, 1)
    //' 由于缺省的連線不帶箭頭,因此需要在連線的末位位置設(shè)置箭頭呆奕,同樣通過CellsSRC獲取對應(yīng)的Cell
    Dim ArrowOfLine As Visio.Cell
    //' 設(shè)置箭頭的類型
    Set ArrowOfLine = Line.CellsSRC(visSectionObject, visRowLine, visLineEndArrow)
    ArrowOfLine.Formula = "5"
    //' 設(shè)置箭頭的大小
    Set ArrowOfLine = Line.CellsSRC(visSectionObject, visRowLine, visLineEndArrowSize)
    ArrowOfLine.Formula = "2"
    Dim LineBeginX As Visio.Cell
    Dim LineEndX As Visio.Cell
    //' 獲得連線的兩端的Cell
    Set LineBeginX = Line.Cells("BeginX")
    Set LineEndX = Line.Cells("EndX")
    //' 通過連接線的名字獲取前面Node的指針域和后面Node的數(shù)據(jù)域?qū)?yīng)的連接點养晋,然后調(diào)用連接線兩端Cell的GlueTo操作進(jìn)行連接,由于從前向后梁钾,因此分別時X2和X4
    Dim CellGlueToRect01 As Visio.Cell
    Set CellGlueToRect01 = PrevNode.PointerShape.Cells("Connections.X2")
    Dim CellGlueToRect02 As Visio.Cell
    Set CellGlueToRect02 = NextNode.InforShape.Cells("Connections.X4")
    LineBeginX.GlueTo CellGlueToRect01
    LineEndX.GlueTo CellGlueToRect02
End Sub

最后绳泉,運行該VBA程序,就可以在Visio的當(dāng)前頁面中繪制出如圖 1 所示的鏈表姆泻。

本文主要做拋磚引玉之用零酪,通過提供一個完整的樣例來展示如何通過VBA編程實現(xiàn)在Visio中進(jìn)行圖形的繪制。通過VBA可以方便的操作各種圖形拇勃,有興趣的讀者可以實現(xiàn)相關(guān)的函數(shù)庫四苇,方便自己組合使用。

如果本文對你有幫助方咆,一定要點贊月腋!記得,別光看不點瓣赂!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末榆骚,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子煌集,更是在濱河造成了極大的恐慌妓肢,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件牙勘,死亡現(xiàn)場離奇詭異职恳,居然都是意外死亡所禀,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進(jìn)店門放钦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來色徘,“玉大人,你說我怎么就攤上這事操禀」硬撸” “怎么了?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵颓屑,是天一觀的道長斤寂。 經(jīng)常有香客問我,道長揪惦,這世上最難降的妖魔是什么遍搞? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮器腋,結(jié)果婚禮上溪猿,老公的妹妹穿的比我還像新娘。我一直安慰自己纫塌,他們只是感情好诊县,可當(dāng)我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著措左,像睡著了一般依痊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上怎披,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天胸嘁,我揣著相機(jī)與錄音,去河邊找鬼钳枕。 笑死缴渊,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的鱼炒。 我是一名探鬼主播衔沼,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼昔瞧!你這毒婦竟也來了指蚁?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤自晰,失蹤者是張志新(化名)和其女友劉穎凝化,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體酬荞,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡搓劫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年瞧哟,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片枪向。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡勤揩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出秘蛔,到底是詐尸還是另有隱情陨亡,我是刑警寧澤,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布深员,位于F島的核電站负蠕,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏倦畅。R本人自食惡果不足惜遮糖,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望滔迈。 院中可真熱鬧止吁,春花似錦被辑、人聲如沸燎悍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽谈山。三九已至,卻和暖如春宏怔,著一層夾襖步出監(jiān)牢的瞬間奏路,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工臊诊, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留鸽粉,地道東北人。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓抓艳,卻偏偏與公主長得像触机,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子玷或,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內(nèi)容