社内で利用する為のツールを作らなきゃならないと思いつつ
数年経ってしまっているのですが、気が重いです。
目的のものはGUIが必要なのですが、個人的に非常に苦手です。
本来であれば、勉強ついでにPythonで と思っていたのですが
GUIが必要となるとC#の方が楽な気がして、仕方無しに
VS2017 Communityエディションをインストールしました。
何もかも忘れてます。 困ったな・・・。
Fusion360と他のCADを併用されている方いらっしゃいますか?
Fusion360は色々なフォーマットのデータを読み込んでくれるので
助かっているのですが、Fusion360上ではこんな感じで表示しているのに
中間フォーマットでエクスポートしたものを、他のCADで読み込んだ際
こんな感じになってガッカリした経験は無いでしょうか?
何で、色が抜けるのか? 僕、理由を知ってます。
実はデータの状態で色が抜けてしまうようです。
ちょっと大げさにしましたが赤印位置にボディがあり
全てルートコンポーネント(一番トップのコンポーネント)ではない位置に
入っています。 原因はこれなんです。
(Upしたデータは、子コンポーネントに入っているような気がしてます)
色を反映させてエクスポートしたいのであれば、全てのボディを
ルートコンポーネントに移動させればOKです。
これって、Tree上でD&Dをやれば済む話ではあるのですが、
対象のボディが案外Treeの深い位置にあり、数が多いと面倒なんです。
・・・そう、面倒。 なので全てのボディをかき集めるスプリクトを
作ってみました。
#FusionAPI_python #Author-kantoku #Description-Collect_All_Body #アクティブなプロダクトの全てのボディをルートにかき集める import adsk.core, adsk.fusion, traceback def run(context): ui = None try: app = adsk.core.Application.get() ui = app.userInterface #確認 msg = '全てのボディをルートコンポーネントにかき集めます。\nよろしいですか?' title = 'ボディかき集め' btn = adsk.core.MessageBoxButtonTypes.OKCancelButtonType icon = adsk.core.MessageBoxIconTypes.QuestionIconType Res = ui.messageBox(msg, title, btn, icon) if Res != adsk.core.DialogResults.DialogOK: return #モロモロ product = app.activeProduct des = adsk.fusion.Design.cast(product) #パラメトリックじゃないとNG des.designType = adsk.fusion.DesignTypes.ParametricDesignType #ルート root = des.rootComponent #ルート以下のコンポーネント cmplst = [] cmplst = Get_Comps(root, cmplst) #全ボディコンテナ bdyslst = [cmp.bRepBodies for cmp in cmplst if cmp.bRepBodies.count > 0] #全ボディ bdylst = [] for bdys in bdyslst: for bdy in bdys: bdylst.append(bdy) if bdylst.count == 0 : return #カットペースト tgtBodies = root.features.cutPasteBodies [tgtBodies.add(bdy) for bdy in bdylst] #おしまい ui.messageBox('Done') except: if ui: ui.messageBox('エラー\n{}'.format(traceback.format_exc())) #全コンポーネント def Get_Comps(comp, complst): occs = comp.occurrences lst = [occ.component for occ in occs] if lst.count == 0: return complst for cmp in lst: complst.append(cmp) Get_Comps(cmp, complst) return complst
Pythonまだまだ駄目だなぁ。見事に二重ループがあるし…。
こんな感じです。
本当は、CATIAのProductからPartを作るコマンドをイメージしていたのですが
異なるDocument間でどうやったらコピペ出来るのか、方法わかりませんでした。
僕はこれで事足りるんですけどね。
こちらの続きです。
Drawのテーブルに最後の列を追加 - C#ATIA
前回のマクロ、ちょっとダメなんです。
セルの文字だけのコピーだったので、フォントのボールド等が正しくなかったのです。
寸法テーブルのサイズ変更する方法をmineさんに教えて
頂いたのですが、実際に使う際、一定しない列数を追加し
テーブルの見出し? も入れたいのです。
結構めんどくさいんです。
そこで修正してみました。
'vba DrawTable_Add_LastColumn ver0.0.2 using-'KCL0.0.12' by Kantoku Option Explicit Private Const Def = "hoge,piyo,huga" 'デフォルト文字 Sub CATMain() 'ドキュメントのチェック If Not CanExecute("DrawingDocument") Then Exit Sub 'テーブル選択 Dim Msg As String Msg = "列を追加するテーブルを選択 // [Esc]=Cancel" Dim Tbl As DrawingTable Set Tbl = KCL.SelectItem(Msg, "DrawingTable") If Tbl Is Nothing Then Exit Sub 'ユーザー Msg = "追加するタイトルを入力 例)hoge,piyo"" Dim Inp As String Inp = InputBox(Msg, "", Def) If Inp = vbNullString Then Exit Sub '追加数列 Dim Txts As Variant: Txts = Split(Inp, ",") Dim AddCnt As Long: AddCnt = UBound(Txts) + 1 '元列数 Dim CntCol As Long: CntCol = Tbl.NumberOfColumns Dim AllColCnt As Long: AllColCnt = CntCol + AddCnt '列追加 Tbl.ComputeMode = CatTableComputeOFF Dim i As Long For i = 1 To AddCnt Call Tbl.AddColumn(CntCol) Next '最後を追加の最初にコピー Call Copy_Column(AllColCnt, CntCol, Tbl) '空欄設置 Call Reset_Column(CntCol + 1, AllColCnt, Tbl) 'タイトル設置 Call Set_Title(Txts, 25#, Tbl) Tbl.ComputeMode = CatTableComputeON End Sub Private Sub Set_Title(ByVal Ary As Variant, _ ByVal Width As Double, _ ByVal Tbl As DrawingTable) Dim Ed As Long: Ed = Tbl.NumberOfColumns Dim St As Long: St = Ed - UBound(Ary) Dim i As Long, Cell As DrawingText Dim Cnt As Long: Cnt = 0 For i = St To Ed Call Tbl.SetColumnSize(i, Width) Set Cell = Tbl.GetCellObject(1, i) Cell.Text = Ary(Cnt) Cnt = Cnt + 1 Cell.TextProperties.Justification = catCenter Next End Sub Private Sub Reset_Column(ByVal A As Long, _ ByVal B As Long, _ ByVal Tbl As DrawingTable) Dim Vw As DrawingView: Set Vw = Tbl.Parent.Parent Dim Dmy As DrawingText: Set Dmy = Vw.Texts.Add("", 0#, 0#) Dmy.TextProperties.Justification = catCenter Dim CntRow As Long: CntRow = Tbl.NumberOfRows Dim Cell As DrawingText Dim i As Long For i = 1 To CntRow Set Cell = Tbl.GetCellObject(i, B) Call Copy_DrwTxtProperties(Cell.TextProperties, _ Dmy.TextProperties) Cell.Text = "" Next For i = B To A + 1 Step -1 Call Copy_Column(i, i - 1, Tbl) Next Dim Sel As Selection Set Sel = KCL.GetParent_Of_T(Vw, "DrawingDocument").Selection With Sel .Clear .Add Dmy .Delete End With End Sub Private Sub Copy_Column(ByVal A As Long, _ ByVal B As Long, _ ByVal Tbl As DrawingTable) Dim CntRow As Long: CntRow = Tbl.NumberOfRows Dim Cell(1) As DrawingText Dim TxtPpt(1) As DrawingTextProperties Dim i As Long For i = 1 To CntRow Set Cell(0) = Tbl.GetCellObject(i, A) Set Cell(1) = Tbl.GetCellObject(i, B) Call Copy_DrwTxtProperties(Cell(0).TextProperties, _ Cell(1).TextProperties) Cell(1).Text = Cell(0).Text Next End Sub Private Sub Copy_DrwTxtProperties(ByVal Tpp1 As DrawingTextProperties, _ ByVal Tpp2 As DrawingTextProperties) With Tpp2 .AnchorPoint = Tpp1.AnchorPoint .Blanking = Tpp1.Blanking .Bold = Tpp1.Bold .Color = Tpp1.Color .FONTNAME = Tpp1.FONTNAME .FONTSIZE = Tpp1.FONTSIZE .FrameName = Tpp1.FrameName .FrameType = Tpp1.FrameType .Italic = Tpp1.Italic .Justification = Tpp1.Justification .Kerning = Tpp1.Kerning .Mirror = Tpp1.Mirror .Overline = Tpp1.Overline .StrikeThru = Tpp1.StrikeThru .Subscript = Tpp1.Subscript .Underline = Tpp1.Underline End With End Sub
見事な肥大化っぷり・・・。
最初の時点ではかなり遅かったのですが、DrawingTable.ComputeModeを
利用するとストレスを感じるほどでは無くなりました。
マクロ実行後、ダイアログが出現しカンマ区切りで文字を入力すると
区切った分の列を追加し、見出しとして入力されます。
作ったけど、使うかなぁ・・・。
仕事が薄い時に、日頃の不満を解消したい。
PowerMill内のフォルダを削除したい時が多々あるのですが、
まとめて削除出来ず、一個一個チマチマやるのが辛いです。
一度に複数のフォルダを削除する為のマクロを作りました。
//PMill_Macro2018 //フォルダー削除 ver0.0.1 function main(string args) { //フォルダリスト string list folderLst = {} call GetFolderNameLIST($args, $folderLst) if is_empty($folderLst) { message error 'フォルダがありません!!' return } string msg = '削除するフォルダーを選択してください' call Exec_DownMenu($folderLst, $msg, 1, $folderLst) if size($folderLst) < 1 { return } //削除 call Msgoff() string path = "" foreach fdr in $folderLst { $path = $args + '\' + replace($fdr, '@', '\') //message info $path string cmd = 'DELETE ' + $args + ' FOLDER "' + $path + '"' call Exec_Cmd(cmd) } call Msgon() //終了 message info 'Done' } //指定した組み込みルートフォルダ内のフォルダ名を取得 function GetFolderNameLIST(string FolderType, output string list Outlst ) { string list Folders = get_folders($FolderType) if (size($Folders) == 0) { return } string list names={} foreach path in $Folders { string name = path $name = replace($name, $FolderType + '\', '') $name = replace($name, '\', '@') int dmy = add_last($names,$name) } $Outlst= $names return } //コマンド function Exec_Cmd(string cmd) { docommand $cmd } function Msgoff() { graphics lock dialogs message off dialogs error off } function Msgon() { graphics unlock dialogs message on dialogs error on } include downmenu.inc
mainのargsは、"Toolpath"等のフォルダ名で、コンテキストメニューから起動させる
タイプです。
過去に、こちらでフォルダ名を取得するものを作りましたが、
イマイチだった為、Forumにあった方法をパクリ参考に
させてもらいました。
フォルダ名リストを取得する - C#ATIA
又、以前作成したプルダウンリストが必要です。
"group" フォルダは犠牲にした、プルダウンリストライブラリ - C#ATIA
Drawの穴寸法/座標寸法テーブルで、最後の列を増やしたい事が
結構あるのですが、恐らく手動では出来ないような気がしてます。
手動で出来ます(コメント部で、mineさんに教えて頂きました)
(方法知っている方いらっしゃいましたら、教えて頂けると助かります)
仕方ないので、マクロを作成しました。
'vba DrawTable_Add_LastColumn ver0.0.1 using-'KCL0.0.12' by Kantoku Option Explicit Sub CATMain() 'ドキュメントのチェック If Not CanExecute("DrawingDocument") Then Exit Sub 'テーブル選択 Dim Msg As String Msg = "最後に列を追加するテーブルを選択 // [Esc]=Cancel" Dim Tbl As DrawingTable Set Tbl = KCL.SelectItem(Msg, "DrawingTable") If Tbl Is Nothing Then Exit Sub '一列追加 Dim CntCol As Long: CntCol = Tbl.NumberOfColumns Call Tbl.AddColumn(CntCol) 'コピー Dim CntRow As Long: CntRow = Tbl.NumberOfRows Dim Txt As String, i As Long For i = 1 To CntRow Txt = Tbl.GetCellString(i, CntCol + 1) Call Tbl.SetCellString(i, CntCol, Txt) Call Tbl.SetCellString(i, CntCol + 1, "") Next End Sub
最後から2番目の位置に列を追加し、最後の列をコピーしつつ
最後の列を空欄にしています。(vbNullStringではNG)
コード的にはくだらないのですが、これを手動でやると本当に
手間がかかるんですよね。Excelの様に複数のセルをまとめて
コピー出来ないですし。
・・・最後に追加出来ない! ってMS製品でも多いですよね?
手抜きメニューに登録しながらマクロを修正していたら
地味なヤツを見つけました。
こんな感じの、丸括弧付きの寸法って何と呼ぶのが正式なんでしょうか?
(きっとJISとかで決まっていると思うのですが)
僕は参考寸法と呼んでいます。 こちらでもそんな記載になってます。
寸法の記入の基本ルール
「2重寸法の禁止」の所に記載されています。
(個人的に重複した寸法は、かなり重罪です)
こちらでは括弧寸法と記載されていました。
括弧寸法の使い方をここまで細かく語るエンジニアはいない | メカ設計のツボ|マザーマシンの元エンジニアが語る
これ、図面を描いているAdvanceCADには、寸法をクリックしただけで
行ってくれる機能があるのですが、CATIAには無いですよね?
これを行うだけのマクロです。
'vba Sample_Draw_Ref_Dimension ver0.0.2 using-'KCL0.0.12' Option Explicit Private Enum Dimension_Value Main_Value = 1 Dual_Value = 2 End Enum Sub CATMain() 'ドキュメントのチェック If Not CanExecute("DrawingDocument") Then Exit Sub Dim Msg$: Msg = "参考/非参考化する寸法を選択 // [Esc]=Cancel" Dim DrwDim As DrawingDimension Dim DimVal As Variant 'DrawingDimValue Dim Bfr$, Afr$, Upr$, Lwr$ Do Set DrwDim = KCL.SelectItem(Msg, "DrawingDimension") If DrwDim Is Nothing Then Exit Sub Set DimVal = DrwDim.GetValue Call DimVal.GetBaultText(Dimension_Value.Main_Value, _ Bfr, Afr, Upr, Lwr) If IsRefDimension(Bfr, Afr) Then '既に参考寸法 Call DimVal.SetBaultText(Dimension_Value.Main_Value, _ Mid(Bfr, 2), _ Left(Afr, Len(Afr) - 1), _ Upr, Lwr) Else 'ただの寸法 Call DimVal.SetBaultText(Dimension_Value.Main_Value, _ "(" & Bfr, _ Afr & ")", _ Upr, Lwr) End If Loop End Sub Private Function IsRefDimension(ByVal Bfr As String, _ ByVal Afr As String) As Boolean IsRefDimension = False If Bfr = vbNullString Or Afr = vbNullString Then Exit Function Dim Tp$, Ed$ Tp = Left(Bfr, 1) Ed = Right(Afr, 1) If Tp = "(" And Ed = ")" Then IsRefDimension = True End Function
寸法のプロパティの [寸法テキスト]タブ [関連テキスト] の
・前側の最初の文字が「(」
・後側の最後の文字が「)」
の二つの条件がそろった時に、丸括弧を外し
そうでないときは丸括弧を追加します。
こんな感じです。
・・・地味
こちらの続きです。
手抜きマクロ起動用メニュー2 - C#ATIA
「Cat_Macro_Menu_Model.bas」の宣言セクション部に幾つか定数を
設けています。お好みで変更してください。
'Cat_Macro_Menu_Model.bas 'using-'KCL0.0.12' 'タグを追記したモジュールをプロジェクトに追加するだけで '自動的にボタンを追加します Const FormTitle = "Macro" '----- メニューの仕様 お好みで --------------------------------------- 'メニューの表示方法 'True-モーダレス表示 False-モーダル表示 Private Const MENU_SHOW_TYPE = True 'メニューを閉じるタイミング 'True-フォームのXボタンを押して閉じます False-ボタンクリック後閉じます Private Const MENU_HIDE_TYPE = True 'メニューのマルチページの設定 '変更する際は '{ タグのグループ番号 : ページのタイトル文字 } 'の状態にして下さい Private Const GROUP_NUMBER_CAPTION = _ "{ 1 : Part }" & _ "{11 : Assy }" & _ "{21 : Draw }" & _ "{51 : Other }" '----------------------------------------------------------------- ・・・
・「MENU_SHOW_TYPE」
メニューの表示で、モーダレスかモーダルかをBoolean型で切り替えられます。
・「MENU_HIDE_TYPE」
メニュー終了タイミングですが、Upしたデータのコメント間違えていました・・。
正しくは上記の状態で、Boolean型で切り替えられます。
ボタンクリック後に終了させるか、表示しっぱなしかです。
実質、「モーダレス + 表示しっぱなし」 か 「モーダル + クリック後終了」
に、なるのだろうと思います。
・「GROUP_NUMBER_CAPTION」
マルチページの分類と表示させる文字になります。
挿入する標準モジュールの {Gp}タグは、こちらの番号にない場合は
ボタンが表示されません。
続いて、フォームコードの「Cat_Macro_Menu_View.frm」の宣言セクション部です。
フォームのレイアウト等はこちらの定数で、若干調整が可能です。
(環境によってはボタンの文字が途切れる等あるかもしれないため・・・))
'Cat_Macro_Menu_View.frm 'メニューのUIです。 'フォーム Private FrmMargin As Variant '上,下,左,右のボタン配置のマージン Private Const ADJUST_F_W = 13 'フォームの左右の調整幅 Private Const ADJUST_F_H = 30 'フォームの上下の調整幅 'マルチページ Private Const ADJUST_M_W = 5 'マルチページの左右の調整幅 Private Const ADJUST_M_H = 18 'マルチページの上下の調整幅 'ボタン Private Const BTN_W = 70 'ボタンの幅-フォームの最低幅以下にすると余白が増える Private Const BTN_H = 20 'ボタン1個の高さ ・・・
各マルチページに該当するボタンがない場合は、ページ自体が作成されません。
又、各ページに配置されるボタンの順番は、モジュール名でソートして表示させています。
好みの順番で表示させたい場合は・・・・モジュール名を工夫してください。
(良いアイデアが思いつきませんでした)
あと何か有ったかなぁ? マクロ用のメニューなんて今更だし。
念の為、このままではOffice製品では機能しないです。
プロジェクト名・パスの取得方法は、imihitoさんが
こちらのコメント欄に記載して頂いてます。
実行中のプロジェクト名とパス取得する - C#ATIA
ボタン押した際の各マクロの実行方法は、こちらの
「Application.Run」の方法で可能だろうと思います。
外部のマクロを実行する2 - C#ATIA
正規表現もまともに使ったの初めてでしたし、まさか自分が
CallByNameを使うコードを書く日が来るとは思っていませんでしたよ。