The initial attempt read psoSelect.AllowSpaces = true;
I've been faffing about trying to make it work and thus the code I copied is wrong. Take my word that with the AllowSpaces = true, when I use the spacebar it's acting as though I want to accept the current command line contents.
namespace MultiBlockClass
{
public class Commands
{
[CommandMethod("MultiBlocks")]
public void MultiBlocks()
{
Database sourceDb;
bool wblock = false;
Database db = HostApplicationServices.WorkingDatabase;
OpenFileDialog coordsSelectDialog = getCoordsFile();
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
string blockName = "";
ObjectId blockId;
bool isStringValid = false;//Enabling us to loop until string is valid or user cancels
while (!isStringValid)
{
PromptStringOptions psoSelect = new PromptStringOptions("Key-in Block Name or <Enter> to Select Wblock");
psoSelect.AllowSpaces = true;
PromptResult prBlockSelected = ed.GetString(psoSelect);
if (prBlockSelected.Status == PromptStatus.Cancel)
return;
else if (prBlockSelected.Status != PromptStatus.OK)
System.Windows.Forms.MessageBox.Show("Error With User Input - Try Again or Cancel", "Error");
else if (!String.IsNullOrEmpty(prBlockSelected.StringResult))
{
isStringValid = true;
blockName = prBlockSelected.StringResult;
break;//Database-resident "Block Reference" chosen - pending validation
}
isStringValid = true; //No more looping
wblock = true;
}
using (Transaction trans = db.TransactionManager.StartTransaction())
{
BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
if (!wblock)//Search Block Table for database-resident Block Reference
{
//Iterate the Block Table, searching for our user-specified "Block Reference"
if (!bt.Has(blockName.ToString()) && !wblock)
{
System.Windows.Forms.MessageBox.Show("Specified 'Block Reference' Not Valid in This Document - Application Terminated"
, "Input Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
return;
}
blockId = bt[blockName.ToString()];//Essentially our "Block Definition"
}
else//We need to select an external DWG file as our insertable Wblock
{
//Set a reference to the source database via an OpenFileDialog
sourceDb = new Database();
OpenFileDialog open = new OpenFileDialog("Select DWG", "Select File", "dwg",
"WBlock Selection", OpenFileDialog.OpenFileDialogFlags.NoUrls);
open.ShowDialog();
string filename = open.Filename;//Target database filename
sourceDb.ReadDwgFile(filename, FileShare.Read, true, null);//Source database "wrapped"
blockId = db.Insert("newBlock", sourceDb, true);
}
using (TextReader coordsFile = new StreamReader(coordsSelectDialog.Filename))
{
while (coordsFile.Peek() > 0)//Until all lines of our stream have been read in
{
try
{
string lineRead = coordsFile.ReadLine();
if (String.IsNullOrEmpty(lineRead))//Shouldn't get to this stage, but just in-case...
break;
string[] lineSeparated = lineRead.Trim().Split(' ');
//Convert first two elements to double for our insertion point
Point3d insPoint = new Point3d(Double.Parse(lineSeparated[0]), Double.Parse(lineSeparated[1]), 0);
BlockReference blockRef = new BlockReference(insPoint, blockId);
//Add to ModelSpace immediately to ensure successful attribute population
BlockTableRecord mSpace = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
mSpace.AppendEntity(blockRef);
trans.AddNewlyCreatedDBObject(blockRef, true);
if (lineSeparated.Count() > 2)//If true, we have attribute data
{
BlockTableRecord thisBlock = (BlockTableRecord)trans.GetObject(blockId, OpenMode.ForRead);
int counter = 2; //Element in "lineSeparated" where attribute information will begin - after coordinates
foreach (ObjectId obj in thisBlock)
{
Entity ent = (Entity)trans.GetObject(obj, OpenMode.ForRead);
if (ent is AttributeDefinition)
{
AttributeDefinition attDef = (AttributeDefinition)(ent);
AttributeReference attRef = new AttributeReference();
attRef.SetPropertiesFrom(ent);
attRef.TextString = lineSeparated[counter];
attRef.Position = new Point3d(blockRef.Position.X + attDef.Position.X,
blockRef.Position.Y + attDef.Position.Y,
0);
attRef.Tag = attDef.Tag;
attRef.Height = attDef.Height;
attRef.Rotation = attDef.Rotation;
//Add this attribute to the "Block Reference" & the transaction
blockRef.AttributeCollection.AppendAttribute(attRef);
trans.AddNewlyCreatedDBObject(attRef, true);
//Increment the counter so the next attribute will utilise the next array element
counter++;
}
}
}
}
catch
{
System.Windows.Forms.MessageBox.Show("Error - Application Terminated", "Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
return;
}
}
}
//Complete by adding Block Referenc to transaction
trans.Commit();
}
}
public OpenFileDialog getCoordsFile()
{
OpenFileDialog coordsSelectDialog = new OpenFileDialog("Coodinate Selection", "", "txt",
"Select a Coordinate File", OpenFileDialog.OpenFileDialogFlags.NoUrls);
bool coordsSelected = false;//So we can loop until valid file selected or user cancels
while (!coordsSelected)
{
System.Windows.Forms.DialogResult coordsResult = coordsSelectDialog.ShowDialog();
if (coordsResult == System.Windows.Forms.DialogResult.Cancel)
return null;
if (coordsResult != System.Windows.Forms.DialogResult.OK)
System.Windows.Forms.MessageBox.Show("Select Another File");
else
coordsSelected = true; //Loop will no longer execute & we have a valid file
}
return coordsSelectDialog;
}
}
}
If anyone can verify whether it works as expected on their machine it would be appreciated.
The text file will need to have values separated by a blank space and the block will need to be entered by typing it's name.