[CommandMethod("BCSV")]
public static void WriteBlocksToCSV()
{
System.Globalization.CultureInfo oldcult = System.Threading.Thread.CurrentThread.CurrentCulture;
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("EN-us");
Database db = HostApplicationServices.WorkingDatabase;
Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
string fname = @"C:\Test\Block_PART.csv";
// Enter block name to be written
PromptStringOptions psto = new PromptStringOptions("\nEnter block name: ");
psto.AllowSpaces = true;
PromptResult res;
res = ed.GetString(psto);
if (res.Status != PromptStatus.OK)
return;
string blkname = res.StringResult;
ed.WriteMessage("\nBlock Name Entered:\t{0}", blkname);
// put appropriate delimiter here I've used semicolon (it's default delimiter on my local machine)
string sep = ";";
Matrix3d mtx = ed.CurrentUserCoordinateSystem;
List<string> data = new List<string>();
PromptSelectionOptions pso = new PromptSelectionOptions();
pso.MessageForRemoval = "\nNothing selected, try again...";
pso.MessageForAdding = "\nPlease select blocks on screen: ";
TypedValue[] tv = new TypedValue[] { new TypedValue(0, "insert"), new TypedValue(2, blkname), new TypedValue(66, 1) };
SelectionFilter filter = new SelectionFilter(tv);
PromptSelectionResult psr = ed.GetSelection(pso, filter);
if (psr.Status != PromptStatus.OK)
{
ed.WriteMessage("\nSelection Result: {0}", psr.Status);
return;
}
SelectionSet sset = psr.Value;
ed.WriteMessage("\nSelected blocks: {0}", sset.Count);
if (sset.Count == 0)
{
ed.WriteMessage("\nNothing Selected, exit...");
return;
}
using (Transaction tr = db.TransactionManager.StartTransaction())
{
try
{
string headers = string.Format("{0}{8}{1:f3}{8}{2:f3}{8}{3:f3}{8}{4:f3}{8}{5:f3}{8}{6:f3}{8}{7:f3}{8}{9}",
"HANDLE", "X_Coordinate", "Y_Coordinate", "Z_Coordinate", "Rotation", "X_Scale", "Y_Scale", "Z_Scale", sep, "Attributes >>");
data.Add(headers);
foreach (SelectedObject sobj in sset)
{
ObjectId id = sobj.ObjectId;
Entity ent = tr.GetObject(id, OpenMode.ForRead) as Entity;
if (ent == null) return;
BlockReference bref = ent as BlockReference;
if (bref == null) return;
string hdl = bref.Handle.ToString();
Point3d pp = bref.Position.TransformBy(Matrix3d.Identity);
double rot = bref.Rotation;
Scale3d scl = bref.ScaleFactors;
AttributeCollection attids = bref.AttributeCollection;
string attvalues = sep;
foreach (ObjectId attid in attids)
{
AttributeReference attref = tr.GetObject(attid, OpenMode.ForRead) as AttributeReference;
string attval = attref.TextString;
// to avoid writing text like 04-01 as "04 Jan." in csv file add single quote at the start
if (attval.Contains("-")) attval = string.Format("'{0}", attval);
attvalues = attvalues + attval + sep;
}
attvalues = attvalues.TrimEnd(',');
// create delimted text line for every block
string strtmp = string.Format("{0}{8}{1:f3}{8}{2:f3}{8}{3:f3}{8}{4:f3}{8}{5:f3}{8}{6:f3}{8}{7:f3}{9}",
hdl, pp.X, pp.Y, pp.Z, rot, scl.X, scl.Y, scl.Z, sep, attvalues);
data.Add(strtmp);
}
if (data.Count > 1)
{
try
{
if (File.Exists(fname))
{
// delete existing file
File.Delete(fname);// to write always to newly created file
}
using (StreamWriter sw = new StreamWriter(fname, true, Encoding.Default, 4096))
{
foreach (string coords in data)
{
sw.WriteLine(coords);
}
}
}
catch (IOException iex)
{
ed.WriteMessage("\nError while processing the file.:\n{0}\n", iex.Message);
}
catch (System.Exception ex)
{
ed.WriteMessage("\nError writinging data to file.:\n{0}\n", ex.Message);
}
}
}
catch (Autodesk.AutoCAD.Runtime.Exception acex)
{
ed.WriteMessage("\nError occurs in AutoCAD drawing.:\n{0}\n", acex.ToString());
}
catch (System.Exception sys)
{
ed.WriteMessage("\nError:\n{0}\n", sys.ToString());
}
finally
{
System.Diagnostics.Process.Start(fname);
ed.WriteMessage("\n\t---\tDone!\t---\n");
System.Threading.Thread.CurrentThread.CurrentCulture = oldcult;
}
}
}