Community
I write code to select all texts
I want to group texts that have the same position X with a tolerance of 2 units
And output each group on a separate line using StreamWriter
public void export_text()
{
Document acDoc = Application.DocumentManager.MdiActiveDocument;
Database acCurDb = acDoc.Database;
Editor ed = acDoc.Editor;
using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
{
BlockTable acBlkTbl;
acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId,
OpenMode.ForRead) as BlockTable;
BlockTableRecord acBlkTblRec;
acBlkTblRec = acTrans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace],
OpenMode.ForWrite) as BlockTableRecord;
TypedValue[] tv = new TypedValue[1];
tv.SetValue(new TypedValue((int)DxfCode.Start, "text"), 0);
string npath = "D://test.txt";
StreamWriter file = new StreamWriter(npath);
file.WriteLine("List of text in selection: ");
List<DBText> alltext = new List<DBText>();
SelectionFilter filter = new SelectionFilter(tv);
PromptSelectionResult ssPrompt;
ssPrompt = ed.GetSelection(filter);
if (ssPrompt.Status == PromptStatus.OK)
{
SelectionSet ss = ssPrompt.Value;
foreach (SelectedObject sObj in ss)
{
DBText spoint = acTrans.GetObject(sObj.ObjectId, OpenMode.ForWrite) as DBText;
alltext.Add(spoint);
}
// i stop here cant complete the code
//var sotrtext = alltext.GroupBy(t => t.Position.X);
//foreach (DBText item in sotrtext)
//{
// string xx = item.TextString;
// file.WriteLine(xx);
//}
}
acTrans.Commit();
file.Flush();
file.Close();
}
}
Hi,
Try like this:
public static void ExportText()
{
var db = HostApplicationServices.WorkingDatabase;
using (var tr = db.TransactionManager.StartTransaction())
{
var modelSpace = (BlockTableRecord)tr.GetObject(
SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead);
var textGroups = modelSpace
.Cast<ObjectId>()
.Where(id => id.ObjectClass.DxfName == "TEXT")
.Select(id => (DBText)tr.GetObject(id, OpenMode.ForRead))
.GroupBy(txt => Math.Round(txt.Position.X / 2.0) * 2.0);
using(var writer = new StreamWriter(@"D:\test.txt"))
{
writer.WriteLine("List of text in selection: ");
foreach (var group in textGroups)
{
writer.WriteLine(string.Join("|", group.Select(txt => txt.TextString)));
}
}
tr.Commit();
}
}
try this:
[CommandMethod("cieTextGrouping")]
public static void TextGrouping()
{
var acDoc = aApp.Application.DocumentManager.MdiActiveDocument;
var acCurDb = acDoc.Database;
var ed = acDoc.Editor;
var textInfos = new List<TextInfo>();
// select text
var filter = new SelectionFilter(new[] { new TypedValue((int)DxfCode.Start, "TEXT") });
var selectRes = ed.GetSelection(filter);
if (selectRes.Status != PromptStatus.OK /*|| selectRes.Value.Count < 1*/)
{
ed.WriteMessage("\n---- No Selection Found -----\n");
return;
}
var ids = selectRes.Value.GetObjectIds();
// read texts from databaase
using (var acTrans = acCurDb.TransactionManager.StartTransaction())
{
// read all texts
foreach (var txtId in ids)
{
var txt = txtId.GetObject(OpenMode.ForRead) as DBText;
textInfos.Add(new TextInfo(txt.TextString, txt.Position.X, txt.Position.Y));
}
}
if (textInfos.Count < 2)
{
ed.WriteMessage("too small number of text");
return;
}
// sort txts based on X
textInfos = textInfos.OrderBy(txt => txt.X).ToList();
// grouping txt with same position
double tolorence = 0.5; int currentGroup = 0;
var previous = textInfos.First();
previous.GroupId = currentGroup;
foreach (var current in textInfos.Skip(1))
{
if (current.HasSameX(previous, tolorence) == false)
{
currentGroup++;
}
current.GroupId = currentGroup;
previous = current;
}
// compse string out of texts
var builder = new StringBuilder();
textInfos
.GroupBy(txt => txt.GroupId)
.Select(g => new { Id = g.Key, Texts = g.OrderBy(txt => txt.Y) }) // to order each group by y
.ToList().ForEach(group =>
{
builder.AppendLine(string.Join("\t", group.Texts.Select(g => g.Text)));
});
//ed.WriteMessage($"\n{builder}");
// write to file
using (var file = new System.IO.StreamWriter(@"D:\test.txt"))
{
file.WriteLine(builder.ToString());
}
}
public class TextInfo
{
public TextInfo(string text, double x, double y)
{
Text = text;
X = x;
Y = y;
}
public string Text { get; set; }
public double X { get; set; }
public double Y { get; set; }
public int GroupId { get; set; }
public bool HasSameX(TextInfo other, double epsilon)
{
return (other.X > (this.X - epsilon))
&& (other.X < (this.X + epsilon));
}
}
using aApp = Autodesk.AutoCAD.ApplicationServices;
and if you want to got with @_gile solution (the cleanest solution):
[CommandMethod("cieTextGrouping")]
public static void TextGrouping()
{
var acDoc = aApp.Application.DocumentManager.MdiActiveDocument;
var acCurDb = acDoc.Database;
var ed = acDoc.Editor;
// select text
var filter = new SelectionFilter(new[] { new TypedValue((int)DxfCode.Start, "TEXT") });
var selectRes = ed.GetSelection(filter);
if (selectRes.Status != PromptStatus.OK /*|| selectRes.Value.Count < 1*/)
{
ed.WriteMessage("\n---- No Selection Found -----\n");
return;
}
var ids = selectRes.Value.GetObjectIds();
// read texts from databaase
using (var tr = acCurDb.TransactionManager.StartTransaction())
{
var textGroups= ids
//.Where(id => id.ObjectClass.DxfName == "TEXT")
.Select(id => (DBText)tr.GetObject(id, OpenMode.ForRead))
.GroupBy(txt => Math.Round(txt.Position.X / 2.0) * 2.0);
using (var writer = new StreamWriter(@"C:\Users\essam\OneDrive\Desktop\t\New Text Document.txt"))
{
writer.WriteLine("List of text in selection: ");
foreach (var group in textGroups)
{
writer.WriteLine(string.Join("|", group.Select(txt => txt.TextString)));
}
}
}
}