Im trying to modify a .dwg file and overwrite the .dwg file once done, all that without opening it in autocad. I've read about RealDWG but the goal here is not to be in a standalone mode. the autocad plugin runs from autocad and needs to modify and write to some .dwg files that are not opened in the current project. So far I create a Database object and Read the .dwg file into it but im having errors when I want to rewrite into it. Here is the code its in C#,
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
namespace ModifyClosedDWG
{
public class DWGEditor
{
private static string filepath = #"E:\...\DrawingTest.dwg";
[CommandMethod("modifyDWG")]
public void addTextToDWG()
{
Database workingDB = HostApplicationServices.WorkingDatabase;
Editor ed = doc.Editor;
Database db = new Database(false, true);
try
{
db.ReadDwgFile(filepath, System.IO.FileShare.ReadWrite, false, "");
db.CloseInput(true);
HostApplicationServices.WorkingDatabase = db;
}
catch (Autodesk.AutoCAD.Runtime.Exception e)
{
ed.WriteMessage("\nUnable to read drawing file : " + e.StackTrace);
return;
}
using (BlockTable bt = db.BlockTableId.Open(OpenMode.ForRead) as BlockTable)
{
using (BlockTableRecord btr = bt[BlockTableRecord.ModelSpace].Open(OpenMode.ForWrite) as BlockTableRecord)
{
MText objText = new MText();
objText.SetDatabaseDefaults();
objText.Location = new Autodesk.AutoCAD.Geometry.Point3d(2, 2, 0);
objText.Contents = "added text in a closed .dwg file!";
objText.TextStyleId = db.Textstyle;
btr.AppendEntity(objText);
}
}
HostApplicationServices.WorkingDatabase = workingDB;
db.SaveAs(filepath, DwgVersion.Current);
}
}
}
the error output :
Autodesk.AutoCAD.Runtime.Exception: eWasOpenForWrite
at Autodesk.AutoCAD.DatabaseServices.Database.SaveAs(String fileName, DwgVersion version)
at ModifyClosedDWG.DWGEditor.addTextToDWG() in E:\PROJETS\ELI017\07 In Works documents\VisualC#Projects\ModifyClosedDWG\ModifyClosedDWG\DWGEditor.cs:line 64
at Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorker(MethodInfo mi, Object commandObject, Boolean bLispFunction)
at Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorkerWithExceptionFilter(MethodInfo mi, Object commandObject, Boolean bLispFunction)
at Autodesk.AutoCAD.Runtime.PerDocumentCommandClass.Invoke(MethodInfo mi, Boolean bLispFunction)
at Autodesk.AutoCAD.Runtime.CommandClass.CommandThunk.Invoke()
I found the solution so I'll put the new code here...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
namespace ModifyClosedDWG
{
public class DWGEditor
{
private static string filepath = #"E:\PROJETS\ELI017\07 In Works documents\dwg\DrawingTest.dwg";
[CommandMethod("modifyDWG")]
public void addTextToDWG()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Database workingDB = HostApplicationServices.WorkingDatabase;
Database db = new Database(false, true);
try
{
db.ReadDwgFile(filepath, System.IO.FileShare.ReadWrite, false, "");
db.CloseInput(true);
HostApplicationServices.WorkingDatabase = db;
}
catch (Autodesk.AutoCAD.Runtime.Exception e)
{
ed.WriteMessage("\nUnable to open .dwg file : " + e.StackTrace);
return;
}
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
MText objText = new MText();
objText.SetDatabaseDefaults();
objText.Location = new Autodesk.AutoCAD.Geometry.Point3d(2, 2, 0);
objText.Contents = "added text in a closed .dwg file!";
objText.TextStyleId = db.Textstyle;
btr.AppendEntity(objText);
tr.AddNewlyCreatedDBObject(objText, true);
tr.Commit();
}
HostApplicationServices.WorkingDatabase = workingDB;
db.SaveAs(filepath, DwgVersion.Current);
}
}
}
Related
Here is my code so far:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Office.Interop.Word;
using Word = Microsoft.Office.Interop.Word;
namespace WordIterator
{
class LoadDocument
{
public static Document Default()
{
try
{
return AnyDoc(Filepath.Full());
}
catch
{
throw new Exception("Error loading default document.");
}
}
public static Document AnyDoc(string filepath)
{
try
{
object fileName = filepath;
Application wordApp = new Application { Visible = true };
Document aDoc = wordApp.Documents.Open(ref fileName, ReadOnly: false, Visible: true);
aDoc.Activate();
return (aDoc);
}
catch
{
throw new Exception("Error loading document " + filepath + "!");
}
}
}
}
//Main class
namespace WordIterator
{
class Program
{
static void Main(string[] args)
{
Document doc = LoadDocument.Default();
doc.SaveAs2(Filepath.Full().Replace(".docx", "_2.docx"));
Document doc2 =
LoadDocument.AnyDoc(#"C:\Users\netha\Documents\FSharpTest\FTEST\ftestdoc3_2.docx");
What i'm trying to do:
Open a word document(do some stuff with it)
Save it as _2.docx
Then open _2.docx(do some stuff with it)
However the second document keeps opening as read-only, I have it set as read-only false and I've even restarted my computer to make sure it shouldn't be read-only.
Does anyone know why this is opening as Read-Only?
Thank you for any assistance
It is opening as read-only as you do SaveAs "_2.docx" and then you are trying to open the save document again. I would recommend you to close the active tab and then open the document.
You could use the following code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Office.Interop.Word;
using Word = Microsoft.Office.Interop.Word;
using System.IO;
namespace WordIterator
{
class Program
{
static void Main(string[] args)
{
string FilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Test.docx");
Document doc = null;
Application wordApp1 =new Application();
Application wordApp2 = new Application();
string FilePath2 = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Test_2.docx");
try
{
object fileName = FilePath;
object fileName2 = FilePath2;
wordApp1 = new Application { Visible = true };
doc = wordApp1.Documents.Open(ref fileName, ReadOnly: false, Visible: true);
doc.SaveAs2(FilePath.Replace(".docx", "_2.docx"));
doc.Close();
Document doc2 = wordApp1.Documents.Open(ref fileName2, ReadOnly: false, Visible: true);
}
catch (Exception ex)
{
}
finally
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(doc);
System.Runtime.InteropServices.Marshal.ReleaseComObject(wordApp1);
}
}
}
}
I am getting below error message while executing code:
Additional information: The process cannot access the file 'C:\Users\Administrator\Desktop\Project\Source \New Bitmap Image.bmp' because it is being used by another process.
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace MoveFiles
{
class Program
{
static void Main(string[] args)
{
string SourceFile = #"C:\Users\Administrator\Desktop\Project\Source ";
string Destination = #"C:\Users\Administrator\Desktop\Project\Destination";
string[] piclist = Directory.GetFiles(SourceFile, "*.bmp");
foreach (string f in piclist)
{
SourceFile.Clone();
Console.WriteLine(f);
File.Copy(Path.Combine(SourceFile, f), Path.Combine(Destination, f), true);
}
}
}
}
Please try using this, this is to copy across one file.
Note: This is a code running on a button click on windows form.
OpenFileDialog obj = new OpenFileDialog();
obj.ShowDialog();
string startLoc = obj.FileName;
string destinationlocation = #"D:\Pictures";
string destinationfile = Path.Combine(destinationlocation, obj.SafeFileName);
if (!Directory.Exists(destinationlocation))
{
Directory.CreateDirectory(destinationlocation);
}
File.Copy(obj.FileName, destinationfile);
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.Schema;
using System.IO;
using System.Xml.XmlConfiguration;
using OATAssetTracking.Solution.Presenter;
namespace WindowsFormsApplication2
{
public class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
string path = "SearchDefinition.xml";
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add(null, #"D:\searchDefinition.xsd");
Exception firstException = null;
var settings = new XmlReaderSettings
{
Schemas = schemas,
ValidationType = ValidationType.Schema,
ValidationFlags =
XmlSchemaValidationFlags.ProcessIdentityConstraints |
XmlSchemaValidationFlags.ReportValidationWarnings
};
settings.ValidationEventHandler +=
delegate(object sender, ValidationEventArgs args)
{
if (args.Severity == XmlSeverityType.Warning)
{
Console.WriteLine(args.Message);
}
else
{
if (firstException == null)
{
firstException = args.Exception;
}
Console.WriteLine(args.Exception.ToString());
}
};
Search result=null;
using (var input = new StreamReader(path))
{
using (XmlReader reader = XmlReader.Create(input, settings))
{
XmlSerializer ser = new XmlSerializer(typeof(Search));
result = (Search)ser.Deserialize(reader);
}
}
if (firstException != null)
{
throw firstException;
}
MessageBox.Show("Deserialization Done!!!!");
}
}
}
In this one,
Here Search is class name which is generated from XSD
result = (Search)ser.Deserialize(reader);
This above statement works fine in Windows forms Application, but fails to work with Windows Device Project " No errors but just hangs there not executing".
Actually, The problem in the above code was
result = (Search)ser.Deserialize(reader);
XML reader which has been created cannot be used while directly de-serializing it to an object. This kind of above code is supported only in the "Windows Forms Application" in VS2008 and its not getting supported in any kind of "Smart Device Projects".
So, Reader settings can be included and XML errors can be handled by any handlers like ValidationEventHandler.
So, Below code validates the XML against XSD and also de-serializes to the object initialized.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.Schema;
using System.IO;
using OATAssetTracking.Solution.Presenter;
namespace WindowsFormsApplication2
{
public class Program
{
static void Main()
{
string path2 = System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase) + "\\" + "SearchDefinition.xsd";
string path1 = System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase) + "\\" + "SearchDefinition.xml";
XmlSchema schema;
using (var schemaReader = XmlReader.Create(path2))
{
schema = XmlSchema.Read(schemaReader, ValidationEventHandler);
}
var schemas = new XmlSchemaSet();
schemas.Add(schema);
var settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.Schemas = schemas;
settings.ValidationFlags =
XmlSchemaValidationFlags.ProcessIdentityConstraints |
XmlSchemaValidationFlags.ReportValidationWarnings;
settings.ValidationEventHandler += ValidationEventHandler;
using (var validationReader = XmlReader.Create(path1, settings))
{
while (validationReader.Read())
{
}
}
MessageBox.Show("XML verified Successfully....");
XmlSerializer ser = new XmlSerializer(typeof(Search));
Search result = ser.Deserialize(new FileStream(path1, FileMode.Open)) as Search;
MessageBox.Show("Deserilization Done Successfully!!!!");
}
private static void ValidationEventHandler(object sender, ValidationEventArgs args)
{
if (args.Severity == XmlSeverityType.Error)
{
throw args.Exception;
}
}
}
}
I have an application which uses open file dialog to open an excel file and then convert it to .txt and it works fine, almost. Currently it can only read tables with only numbers in them but I need to add a function so that it could also read letters. What should I change to make it able to read letters/words as well as numbers?
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OleDb;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : System.Windows.Window
{
public MainWindow()
{
InitializeComponent();
}
private void BtnFileOpen_Click(object sender, RoutedEventArgs e)
{
var fileDialog = new System.Windows.Forms.OpenFileDialog();
var result = fileDialog.ShowDialog();
switch (result)
{
case System.Windows.Forms.DialogResult.OK:
var file = fileDialog.FileName;
TxtFile.Text = file;
TxtFile.ToolTip = file;
break;
case System.Windows.Forms.DialogResult.Cancel:
default:
TxtFile.Text = null;
TxtFile.ToolTip = null;
break;
}
}
public void convert_Click(object sender, RoutedEventArgs e)
{
// Configure save file dialog box
Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
dlg.FileName = "Document"; // Default file name
dlg.DefaultExt = ".txt"; // Default file extension
dlg.Filter = "Text documents (.txt)|*.txt"; // Filter files by extension
// Show save file dialog box
Nullable<bool> result = dlg.ShowDialog();
// Process save file dialog box results
if (result == true)
{
// Save document
string filename = dlg.FileName;
exportExcelToTxt(TxtFile.Text, filename);
}
}
static void exportExcelToTxt(string excelFilePath, string outputTxtPath)
{
Dictionary<string, List<long>> values = new Dictionary<string, List<long>>();
using (OleDbConnection excelConnection = new OleDbConnection(string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 12.0 XML;HDR=YES\"", excelFilePath)))
{
excelConnection.Open();
string firstSheet = getFirstSheetName(excelConnection);
using (OleDbCommand cmd = excelConnection.CreateCommand())
{
cmd.CommandText = string.Format("SELECT * FROM [{0}]", firstSheet);
using (OleDbDataAdapter da = new OleDbDataAdapter(cmd))
{
using (DataTable dt = new DataTable())
{
da.Fill(dt); // Getting all the data in the sheet
foreach (DataRow item in dt.Rows)
{
List<long> toAdd = new List<long>();
string key = item[0] as string;
for (int i = 1; i < dt.Columns.Count; i++)
{
toAdd.Add(Convert.ToInt64(item[i]));
}
values.Add(key, toAdd); // Associating all the "numbers" to the "Name"
}
}
}
}
}
StringBuilder toWriteToTxt = new StringBuilder();
foreach (KeyValuePair<string, List<long>> item in values)
{
// Formatting the output
toWriteToTxt.Append(string.Format("{0}:", item.Key));
foreach (long val in item.Value.Distinct())
{
toWriteToTxt.AppendFormat("\t{0} * {1}\r\n", item.Value.Where(f => f == val).Count(), // Amount of occurrencies of each number
val);
}
}
// Writing the TXT
using (FileStream fs = new FileStream(outputTxtPath, FileMode.Create))
{
using (StreamWriter sw = new StreamWriter(fs))
{
sw.Write(toWriteToTxt.ToString());
}
}
}
static string getFirstSheetName(OleDbConnection excelConnection)
{
using (DataTable ExcelTables = excelConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new Object[] { null, null, null, "TABLE" }))
{
return ExcelTables.Rows[0]["TABLE_NAME"].ToString();
}
}
}
}
You should not convert the values to long in this line:
toAdd.Add(Convert.ToInt64(item[i]));
Also replace all List<long> with List<string>, this should cover pretty much the issue.
There is code in MSDN for printing rdlc without preview in web application but it does not work when i implement in IIS...is there any solution for this ....or any code which work in on print of rdlc without preview
here is the link http://msdn.microsoft.com/en-us/library/ms252091.aspx
It does not give any exception but also does not print the report
on MSDN they said create a console application but I need it in asp.net web application which run in IIS.
using System;
using System.IO;
using System.Data;
using System.Text;
using System.Drawing.Imaging;
using System.Drawing.Printing;
using System.Collections.Generic;
using Microsoft.Reporting.WebForms;
using System.Data.SqlClient;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Windows.Forms;
///<summary>
/// Summary description for Printing
/// this is the cool code found on MSDN site to print labels out without preview
/// abhay maini
///</summary>
publicclassPrinting : IDisposable
{
public Printing()
{
//
// TODO: Add constructor logic here
//
}
publicint m_currentPageIndex;
publicIList<Stream> m_streams;
// Routine to provide to the report renderer, in order to
// save an image for each page of the report.
publicStream CreateStream(string name,string fileNameExtension, Encoding encoding,string mimeType, bool willSeek)
{
string CurrentDrive;
CurrentDrive = Application.StartupPath.ToString();Stream stream = newFileStream("C:\\Labels\\" + name + "." + fileNameExtension, FileMode.Create);
m_streams.Add(stream);
return stream;
}
publicvoid Export(LocalReport report)
{
string deviceInfo =
"<DeviceInfo>" +
" <OutputFormat>EMF</OutputFormat>" +
" <PageWidth>4.0in</PageWidth>" +
" <PageHeight>2.0in</PageHeight>" +
" <MarginTop>0.00in</MarginTop>" +
" <MarginLeft>0.00in</MarginLeft>" +
" <MarginRight>0.00in</MarginRight>" +
" <MarginBottom>0.00in</MarginBottom>" +
"</DeviceInfo>";
Warning[] warnings;m_streams = newList<Stream>();
report.Render("Image", deviceInfo, CreateStream, out warnings);
foreach (Stream stream in m_streams)
stream.Position = 0;
}
// Handler for PrintPageEvents
publicvoid PrintPage(object sender, PrintPageEventArgs ev)
{
Metafile pageImage = newMetafile(m_streams[m_currentPageIndex]);
ev.Graphics.DrawImage(pageImage, ev.PageBounds);
m_currentPageIndex++;
ev.HasMorePages = (m_currentPageIndex < m_streams.Count);
}
publicvoid Print(string PrinterName)
{
// const string printerName = PrinterName;
if (m_streams == null || m_streams.Count == 0)
return;
PrintDocument printDoc = newPrintDocument();
printDoc.PrinterSettings.PrinterName = PrinterName;
if (!printDoc.PrinterSettings.IsValid)
{
string msg = String.Format(
"Can't find printer \"{0}\".", PrinterName);
MessageBox.Show(msg, "Print Error");return;
}
printDoc.PrintPage += newPrintPageEventHandler(PrintPage);
printDoc.Print();
}
// Create a local report for Report.rdlc, load the data,
// export the report to an .emf file, and print it.
publicvoid Run(string ReportName, string PrinterName, DataTable MyDataTable,string DSstring)
{
LocalReport report = newLocalReport();
report.ReportPath = ReportName;
report.DataSources.Clear();
report.DataSources.Add(newReportDataSource(DSstring, MyDataTable));
Export(report);
m_currentPageIndex = 0;
Print(PrinterName);
}
publicvoid Dispose()
{
if (m_streams != null)
{
foreach (Stream stream in m_streams)
stream.Close();
m_streams = null;
}
}
}
The above class can be called as below behind text change event:
protectedvoid TxtScanId_TextChanged(object sender, EventArgs e)
{
string sqlPrintScanID = "SELECT [ScanID], [LoadID], [tempVRMA], [CustPalletID], [TypeOfAsset] FROM [SerialScanDetail] WHERE [ScanID]=" + TxtScanId.Text + "";
string strConnection = ConfigurationManager.ConnectionStrings["RevisionConnectionString"].ToString();
SqlConnection conn = newSqlConnection(strConnection);
SqlDataAdapter da = newSqlDataAdapter();
da.SelectCommand = newSqlCommand(sqlPrintScanID, conn);
DataSet ds = newDataSet();
da.Fill(ds, "RevisionDataSet_SerialScanDetail");
//ReportViewer1.LocalReport.Refresh();
NewPrinting.Run(#"Reports\Report_ScanID.rdlc", "Eltron 2442", ds.Tables[0], "RevisionDataSet_SerialScanDetail");
}
I would suggest making use of the ReportViewer class.
ReportViewer reportViewer = new ReportViewer();
reportViewer.LocalReport.ReportPath = "ReportPath";
reportViewer.LocalReport.DataSources.Add(new ReportDataSource("data", data));
byte[] byteInfo;
byteInfo = reportViewer.LocalReport.Render("Image", deviceInfo, CreateStream, out warnings);
MemoryStream ms = new MemoryStream(byteInfo);
Image returnImage = Image.FromStream(ms);
returnImage is then an image data type that you can display/print.
I see you making a call to render but not assigning the value to use, this combined with not using a report viewer could be the problem.
The reason MSDN suggest making a console application is that it is a good idea to do a proof of concept in a basic program such as a console, get the result you want, then port that code into your desired environment.