C#
using Autodesk.AutoCAD.DatabaseServices;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LineListEx
{
public class PipeGroupData
{
public string LineInfo { get; set; }
public string Remarks { get; set; }
// 内部管理用
public List<ObjectId> ObjectIds { get; set; }
public PipeGroupData(string lineInfo, string remarks = "")
{
LineInfo = lineInfo;
Remarks = remarks;
ObjectIds = new List<ObjectId>();
}
// LineInfo が同じなら同一グループ
public bool EqualsAttributes(string lineInfo)
{
return this.LineInfo == lineInfo;
}
}
}
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using App = Autodesk.AutoCAD.ApplicationServices.Application;
//using System.Windows.Forms;
namespace LineListEx
{
public class LineListCommand
{
[CommandMethod("AddPipeLine")]
public void AddPipeline()
{
Document doc = App.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
try
{
// 1. 入力方法の選択
PromptKeywordOptions pKeyOpts = new PromptKeywordOptions(
"\nラインナンバー入力方法を選んでください [Input(直接入力)/Select(図面上の文字列を選択)]: ",
"Input Select"
);
pKeyOpts.AllowNone = false;
PromptResult pKeyRes = ed.GetKeywords(pKeyOpts);
if (pKeyRes.Status != PromptStatus.OK) return;
string lineNo = "";
if (pKeyRes.StringResult == "Input")
{
// 2. 直接入力
PromptStringOptions pStrOpts = new PromptStringOptions("\nラインナンバーを入力してください: ");
pStrOpts.AllowSpaces = false;
PromptResult pStrRes = ed.GetString(pStrOpts);
if (pStrRes.Status != PromptStatus.OK) return;
lineNo = pStrRes.StringResult;
}
else if (pKeyRes.StringResult == "Select")
{
// 3. 図面上のテキスト選択
PromptEntityOptions peo = new PromptEntityOptions("\nラインナンバーとして使用するテキストを選択してください: ");
peo.SetRejectMessage("\nテキストを選択してください。");
peo.AddAllowedClass(typeof(DBText), true);
peo.AddAllowedClass(typeof(MText), true);
PromptEntityResult per = ed.GetEntity(peo);
if (per.Status != PromptStatus.OK) return;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
Entity ent = tr.GetObject(per.ObjectId, OpenMode.ForRead) as Entity;
if (ent is DBText dbText)
lineNo = dbText.TextString;
else if (ent is MText mText)
lineNo = mText.Text;
tr.Commit();
}
}
if (string.IsNullOrEmpty(lineNo))
{
ed.WriteMessage("\nラインナンバーが取得できませんでした。");
return;
}
// 4. オブジェクト選択
PromptSelectionOptions selOpts = new PromptSelectionOptions();
selOpts.MessageForAdding = "\nラインナンバーを付与するオブジェクトを選択してください: ";
PromptSelectionResult selRes = ed.GetSelection(selOpts);
if (selRes.Status != PromptStatus.OK) return;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// 既存のRemarksを取得
string existingRemarks = GetExistingRemarks(db, tr, lineNo);
// 選択されたオブジェクトに保存
foreach (SelectedObject selObj in selRes.Value)
{
if (selObj == null) continue;
SaveLineInfoAndRemarks(tr, selObj.ObjectId, lineNo, existingRemarks);
}
tr.Commit();
}
ed.WriteMessage("\n選択した全てのオブジェクトにラインナンバーを保存しました。");
}
catch (System.Exception ex)
{
ed.WriteMessage($"\nエラー: {ex.Message}");
}
}
// ★ 既存 LineInfo があれば Remarks を返す(なければ空)
private string GetExistingRemarks(Database db, Transaction tr, string lineNo)
{
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
foreach (ObjectId id in btr)
{
Entity ent = tr.GetObject(id, OpenMode.ForRead) as Entity;
if (ent?.ExtensionDictionary.IsValid != true) continue;
DBDictionary extDict = tr.GetObject(ent.ExtensionDictionary, OpenMode.ForRead) as DBDictionary;
if (extDict.Contains("LineInfo"))
{
Xrecord xrec = tr.GetObject(extDict.GetAt("LineInfo"), OpenMode.ForRead) as Xrecord;
// ★ 修正版 TypedValue 配列アクセス
TypedValue[] values = xrec?.Data?.AsArray();
string info = "";
if (values != null && values.Length > 0)
info = values[0].Value?.ToString() ?? "";
if (info == lineNo && extDict.Contains("Remarks"))
{
Xrecord xrecRem = tr.GetObject(extDict.GetAt("Remarks"), OpenMode.ForRead) as Xrecord;
TypedValue[] remValues = xrecRem?.Data?.AsArray();
if (remValues != null && remValues.Length > 0)
return remValues[0].Value?.ToString() ?? "";
else
return "";
}
}
}
return ""; // 新規の場合は空
}
// ★ LineInfo と Remarks を保存する共通関数
private void SaveLineInfoAndRemarks(Transaction tr, ObjectId objId, string lineNo, string remarks)
{
if (!objId.IsValid) return;
Entity ent = tr.GetObject(objId, OpenMode.ForWrite) as Entity;
if (ent == null) return;
if (!ent.ExtensionDictionary.IsValid)
ent.CreateExtensionDictionary();
DBDictionary extDict = tr.GetObject(ent.ExtensionDictionary, OpenMode.ForWrite) as DBDictionary;
// LineInfo 保存
SaveOrUpdateXrecord(tr, extDict, "LineInfo", lineNo);
// Remarks 保存
SaveOrUpdateXrecord(tr, extDict, "Remarks", remarks);
}
// ★ 既存 Xrecord を削除して上書き
private void SaveOrUpdateXrecord(Transaction tr, DBDictionary extDict, string key, string value)
{
if (extDict.Contains(key))
{
ObjectId oldId = extDict.GetAt(key);
tr.GetObject(oldId, OpenMode.ForWrite).Erase();
}
Xrecord xrec = new Xrecord
{
Data = new ResultBuffer(new TypedValue((int)DxfCode.Text, value ?? ""))
};
extDict.SetAt(key, xrec);
tr.AddNewlyCreatedDBObject(xrec, true);
}
[CommandMethod("GetPipeLine")]
public void GetPipeLine()
{
Document doc = App.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
try
{
PromptEntityOptions peo = new PromptEntityOptions("\nラインナンバーを確認するオブジェクトを選択してください: ");
PromptEntityResult per = ed.GetEntity(peo);
if (per.Status != PromptStatus.OK) return;
string targetLineNo = null;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
Entity ent = tr.GetObject(per.ObjectId, OpenMode.ForRead) as Entity;
if (ent != null && ent.ExtensionDictionary.IsValid)
{
DBDictionary extDict = tr.GetObject(ent.ExtensionDictionary, OpenMode.ForRead) as DBDictionary;
if (extDict.Contains("LineInfo"))
{
Xrecord xrec = tr.GetObject(extDict.GetAt("LineInfo"), OpenMode.ForRead) as Xrecord;
// ★ 修正版 TypedValue 配列アクセス
TypedValue[] values = xrec?.Data?.AsArray();
if (values != null && values.Length > 0)
targetLineNo = values[0].Value?.ToString() ?? "";
}
}
tr.Commit();
}
if (string.IsNullOrEmpty(targetLineNo))
ed.WriteMessage("\n選択したオブジェクトにはラインナンバーがありません。");
else
ed.WriteMessage($"\n選択オブジェクトのラインナンバー: {targetLineNo}");
}
catch (System.Exception ex)
{
ed.WriteMessage($"\nエラー: {ex.Message}");
}
}
[CommandMethod("ShowPipeInfo")]
public void ShowPipeInfo()
{
Document doc = App.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
List<PipeGroupData> pipeGroups = new List<PipeGroupData>();
try
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
foreach (ObjectId id in btr)
{
Entity ent = tr.GetObject(id, OpenMode.ForRead) as Entity;
if (ent == null) continue;
string lineInfo = "";
string remarks = "";
if (ent.ExtensionDictionary.IsValid)
{
DBDictionary extDict = tr.GetObject(ent.ExtensionDictionary, OpenMode.ForRead) as DBDictionary;
// LineInfo 読み取り
if (extDict.Contains("LineInfo"))
{
Xrecord xrec = tr.GetObject(extDict.GetAt("LineInfo"), OpenMode.ForRead) as Xrecord;
if (xrec != null && xrec.Data != null)
{
TypedValue[] values = xrec.Data.AsArray();
if (values.Length > 0)
lineInfo = values[0].Value.ToString();
}
}
// Remarks 読み取り
if (extDict.Contains("Remarks"))
{
Xrecord xrec = tr.GetObject(extDict.GetAt("Remarks"), OpenMode.ForRead) as Xrecord;
if (xrec != null && xrec.Data != null)
{
TypedValue[] values = xrec.Data.AsArray();
if (values.Length > 0)
remarks = values[0].Value.ToString();
}
}
}
// ★ LineInfo が空ならスキップ
if (string.IsNullOrEmpty(lineInfo)) continue;
// 既存グループを探す
var group = pipeGroups.FirstOrDefault(g => g.EqualsAttributes(lineInfo));
if (group == null)
{
group = new PipeGroupData(lineInfo, remarks);
pipeGroups.Add(group);
}
group.ObjectIds.Add(id);
}
tr.Commit();
}
// フォームを非モーダルで表示
LineInfoForm form = new LineInfoForm(pipeGroups);
form.Show(new WindowWrapper(App.MainWindow.Handle));
}
catch (System.Exception ex)
{
App.ShowAlertDialog("エラー: " + ex.Message);
}
}
}
// AutoCAD のウィンドウを親にするためのラッパー
public class WindowWrapper : IWin32Window
{
private readonly System.IntPtr _hwnd;
public WindowWrapper(System.IntPtr handle) { _hwnd = handle; }
public System.IntPtr Handle => _hwnd;
}
}
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using App = Autodesk.AutoCAD.ApplicationServices.Application;
//using System.Windows.Forms;
namespace LineListEx
{
public class LineListCommand
{
[CommandMethod("AddPipeLine")]
public void AddPipeline()
{
Document doc = App.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
try
{
// 1. 入力方法の選択
PromptKeywordOptions pKeyOpts = new PromptKeywordOptions(
"\nラインナンバー入力方法を選んでください [Input(直接入力)/Select(図面上の文字列を選択)]: ",
"Input Select"
);
pKeyOpts.AllowNone = false;
PromptResult pKeyRes = ed.GetKeywords(pKeyOpts);
if (pKeyRes.Status != PromptStatus.OK) return;
string lineNo = "";
if (pKeyRes.StringResult == "Input")
{
// 2. 直接入力
PromptStringOptions pStrOpts = new PromptStringOptions("\nラインナンバーを入力してください: ");
pStrOpts.AllowSpaces = false;
PromptResult pStrRes = ed.GetString(pStrOpts);
if (pStrRes.Status != PromptStatus.OK) return;
lineNo = pStrRes.StringResult;
}
else if (pKeyRes.StringResult == "Select")
{
// 3. 図面上のテキスト選択
PromptEntityOptions peo = new PromptEntityOptions("\nラインナンバーとして使用するテキストを選択してください: ");
peo.SetRejectMessage("\nテキストを選択してください。");
peo.AddAllowedClass(typeof(DBText), true);
peo.AddAllowedClass(typeof(MText), true);
PromptEntityResult per = ed.GetEntity(peo);
if (per.Status != PromptStatus.OK) return;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
Entity ent = tr.GetObject(per.ObjectId, OpenMode.ForRead) as Entity;
if (ent is DBText dbText)
lineNo = dbText.TextString;
else if (ent is MText mText)
lineNo = mText.Text;
tr.Commit();
}
}
if (string.IsNullOrEmpty(lineNo))
{
ed.WriteMessage("\nラインナンバーが取得できませんでした。");
return;
}
// 4. オブジェクト選択
PromptSelectionOptions selOpts = new PromptSelectionOptions();
selOpts.MessageForAdding = "\nラインナンバーを付与するオブジェクトを選択してください: ";
PromptSelectionResult selRes = ed.GetSelection(selOpts);
if (selRes.Status != PromptStatus.OK) return;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// 既存のRemarksを取得
string existingRemarks = GetExistingRemarks(db, tr, lineNo);
// 選択されたオブジェクトに保存
foreach (SelectedObject selObj in selRes.Value)
{
if (selObj == null) continue;
SaveLineInfoAndRemarks(tr, selObj.ObjectId, lineNo, existingRemarks);
}
tr.Commit();
}
ed.WriteMessage("\n選択した全てのオブジェクトにラインナンバーを保存しました。");
}
catch (System.Exception ex)
{
ed.WriteMessage($"\nエラー: {ex.Message}");
}
}
// ★ 既存 LineInfo があれば Remarks を返す(なければ空)
private string GetExistingRemarks(Database db, Transaction tr, string lineNo)
{
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
foreach (ObjectId id in btr)
{
Entity ent = tr.GetObject(id, OpenMode.ForRead) as Entity;
if (ent?.ExtensionDictionary.IsValid != true) continue;
DBDictionary extDict = tr.GetObject(ent.ExtensionDictionary, OpenMode.ForRead) as DBDictionary;
if (extDict.Contains("LineInfo"))
{
Xrecord xrec = tr.GetObject(extDict.GetAt("LineInfo"), OpenMode.ForRead) as Xrecord;
// ★ 修正版 TypedValue 配列アクセス
TypedValue[] values = xrec?.Data?.AsArray();
string info = "";
if (values != null && values.Length > 0)
info = values[0].Value?.ToString() ?? "";
if (info == lineNo && extDict.Contains("Remarks"))
{
Xrecord xrecRem = tr.GetObject(extDict.GetAt("Remarks"), OpenMode.ForRead) as Xrecord;
TypedValue[] remValues = xrecRem?.Data?.AsArray();
if (remValues != null && remValues.Length > 0)
return remValues[0].Value?.ToString() ?? "";
else
return "";
}
}
}
return ""; // 新規の場合は空
}
// ★ LineInfo と Remarks を保存する共通関数
private void SaveLineInfoAndRemarks(Transaction tr, ObjectId objId, string lineNo, string remarks)
{
if (!objId.IsValid) return;
Entity ent = tr.GetObject(objId, OpenMode.ForWrite) as Entity;
if (ent == null) return;
if (!ent.ExtensionDictionary.IsValid)
ent.CreateExtensionDictionary();
DBDictionary extDict = tr.GetObject(ent.ExtensionDictionary, OpenMode.ForWrite) as DBDictionary;
// LineInfo 保存
SaveOrUpdateXrecord(tr, extDict, "LineInfo", lineNo);
// Remarks 保存
SaveOrUpdateXrecord(tr, extDict, "Remarks", remarks);
}
// ★ 既存 Xrecord を削除して上書き
private void SaveOrUpdateXrecord(Transaction tr, DBDictionary extDict, string key, string value)
{
if (extDict.Contains(key))
{
ObjectId oldId = extDict.GetAt(key);
tr.GetObject(oldId, OpenMode.ForWrite).Erase();
}
Xrecord xrec = new Xrecord
{
Data = new ResultBuffer(new TypedValue((int)DxfCode.Text, value ?? ""))
};
extDict.SetAt(key, xrec);
tr.AddNewlyCreatedDBObject(xrec, true);
}
[CommandMethod("GetPipeLine")]
public void GetPipeLine()
{
Document doc = App.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
try
{
PromptEntityOptions peo = new PromptEntityOptions("\nラインナンバーを確認するオブジェクトを選択してください: ");
PromptEntityResult per = ed.GetEntity(peo);
if (per.Status != PromptStatus.OK) return;
string targetLineNo = null;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
Entity ent = tr.GetObject(per.ObjectId, OpenMode.ForRead) as Entity;
if (ent != null && ent.ExtensionDictionary.IsValid)
{
DBDictionary extDict = tr.GetObject(ent.ExtensionDictionary, OpenMode.ForRead) as DBDictionary;
if (extDict.Contains("LineInfo"))
{
Xrecord xrec = tr.GetObject(extDict.GetAt("LineInfo"), OpenMode.ForRead) as Xrecord;
// ★ 修正版 TypedValue 配列アクセス
TypedValue[] values = xrec?.Data?.AsArray();
if (values != null && values.Length > 0)
targetLineNo = values[0].Value?.ToString() ?? "";
}
}
tr.Commit();
}
if (string.IsNullOrEmpty(targetLineNo))
ed.WriteMessage("\n選択したオブジェクトにはラインナンバーがありません。");
else
ed.WriteMessage($"\n選択オブジェクトのラインナンバー: {targetLineNo}");
}
catch (System.Exception ex)
{
ed.WriteMessage($"\nエラー: {ex.Message}");
}
}
[CommandMethod("ShowPipeInfo")]
public void ShowPipeInfo()
{
Document doc = App.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
List<PipeGroupData> pipeGroups = new List<PipeGroupData>();
try
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
foreach (ObjectId id in btr)
{
Entity ent = tr.GetObject(id, OpenMode.ForRead) as Entity;
if (ent == null) continue;
string lineInfo = "";
string remarks = "";
if (ent.ExtensionDictionary.IsValid)
{
DBDictionary extDict = tr.GetObject(ent.ExtensionDictionary, OpenMode.ForRead) as DBDictionary;
// LineInfo 読み取り
if (extDict.Contains("LineInfo"))
{
Xrecord xrec = tr.GetObject(extDict.GetAt("LineInfo"), OpenMode.ForRead) as Xrecord;
if (xrec != null && xrec.Data != null)
{
TypedValue[] values = xrec.Data.AsArray();
if (values.Length > 0)
lineInfo = values[0].Value.ToString();
}
}
// Remarks 読み取り
if (extDict.Contains("Remarks"))
{
Xrecord xrec = tr.GetObject(extDict.GetAt("Remarks"), OpenMode.ForRead) as Xrecord;
if (xrec != null && xrec.Data != null)
{
TypedValue[] values = xrec.Data.AsArray();
if (values.Length > 0)
remarks = values[0].Value.ToString();
}
}
}
// ★ LineInfo が空ならスキップ
if (string.IsNullOrEmpty(lineInfo)) continue;
// 既存グループを探す
var group = pipeGroups.FirstOrDefault(g => g.EqualsAttributes(lineInfo));
if (group == null)
{
group = new PipeGroupData(lineInfo, remarks);
pipeGroups.Add(group);
}
group.ObjectIds.Add(id);
}
tr.Commit();
}
// フォームを非モーダルで表示
LineInfoForm form = new LineInfoForm(pipeGroups);
form.Show(new WindowWrapper(App.MainWindow.Handle));
}
catch (System.Exception ex)
{
App.ShowAlertDialog("エラー: " + ex.Message);
}
}
}
// AutoCAD のウィンドウを親にするためのラッパー
public class WindowWrapper : IWin32Window
{
private readonly System.IntPtr _hwnd;
public WindowWrapper(System.IntPtr handle) { _hwnd = handle; }
public System.IntPtr Handle => _hwnd;
}
}