Microsoft.Office.Word.Interop 2nd Document keeps opening as read-only - c#

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);
}
}
}
}

Related

How to replace text in Word document using Openxml

I have a simple word document with only a single word "$Hello$". I'm trying to change "$Hello$" to "Goodbye" but nothing happens and there's no errors. How can I get the code working? "$Hello$" is in a paragraph.
using System;
using System.IO;
using System.Text.RegularExpressions;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
namespace OpenXMLTests
{
class Program
{
static void Main(string[] args)
{
String document = "TestDoc.docx";
using (WordprocessingDocument doc = WordprocessingDocument.Open(document, true))
{
Body body = doc.MainDocumentPart.Document.Body;
foreach (Table t in body.Descendants<Table>())
{
String tableName = t.GetFirstChild<TableProperties>().TableCaption.Val;
Console.WriteLine(tableName);
}
string docText = null;
using (StreamReader sr = new StreamReader(doc.MainDocumentPart.GetStream())) //Reads file to string
{
docText = sr.ReadToEnd();
}
docText = docText.Replace("$Hello$", "Goodbye");
using (StreamWriter sw = new StreamWriter(doc.MainDocumentPart.GetStream(FileMode.Create)))
{
sw.Write(docText);
}
}
}
}
}
When I remove this table loop the code works. Not sure whats conflicting
Body body = doc.MainDocumentPart.Document.Body;
foreach (Table t in body.Descendants<Table>())
{
String tableName = t.GetFirstChild<TableProperties>().TableCaption.Val;
Console.WriteLine(tableName);
}
Try to disable AutoSave option.
using (WordprocessingDocument doc =
WordprocessingDocument.Open(document, true, new OpenSettings { AutoSave = false }))
{
...
}
Looks like when AutoSave is enabled and getter of doc.MainDocumentPart.Document.Body is called it causes that doc.MainDocumentPart is not saved properly or it's overriden with original document part.

Additional information: The process cannot access the file 'C:\****** \New Bitmap Image.bmp' because it is being used by another process

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);

Deserialize XML to object in C# using Windows Device Project

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;
}
}
}
}

How to find a text and replace it with an image in C#

I have this code which searches for a text and replace it with an another text in MS word document. I want to do the similar kind of operation. Find the text and replace it with an image. I can pass the file location, image location.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.IO;
using word = Microsoft.Office.Interop.Word;
using System.Runtime.InteropServices;
//using System.Drawing;
namespace WritingIntoDocx
{
[ComVisible(true)]
public interface IMyClass
{
void DocumentDigitalSign(string filep,string findt,string replacet);
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public class Program : IMyClass
{
public void DocumentDigitalSign(string filep, string findt, string replacet)
{
string filepath = filep;
string Findtext = findt;
string ReplaceText = replacet;
word.Application app = new word.Application();
word.Document doc = app.Documents.Open(filepath);
word.Range myStoryRange = doc.Range();
//First search the main document using the Selection
word.Find myFind = myStoryRange.Find;
myFind.Text = Findtext;
myFind.Replacement.Text = ReplaceText;
//myFind.Replacement.
myFind.Forward = true;
myFind.Wrap = word.WdFindWrap.wdFindContinue;
myFind.Format = false;
myFind.MatchCase = false;
myFind.MatchWholeWord = false;
myFind.MatchWildcards = false;
myFind.MatchSoundsLike = false;
myFind.MatchAllWordForms = false;
myFind.Execute(Replace: word.WdReplace.wdReplaceAll);
//'Now search all other stories using Ranges
foreach (word.Range otherStoryRange in doc.StoryRanges)
{
if (otherStoryRange.StoryType != word.WdStoryType.wdMainTextStory)
{
word.Find myOtherFind = otherStoryRange.Find;
myOtherFind.Text = Findtext;
myOtherFind.Replacement.Text = ReplaceText;
myOtherFind.Wrap = word.WdFindWrap.wdFindContinue;
myOtherFind.Execute(Replace: word.WdReplace.wdReplaceAll);
}
// 'Now search all next stories of other stories (doc.storyRanges dont seem to cascades in sub story)
word.Range nextStoryRange = otherStoryRange.NextStoryRange;
while (nextStoryRange != null)
{
word.Find myNextStoryFind = nextStoryRange.Find;
myNextStoryFind.Text = Findtext;
myNextStoryFind.Replacement.Text = ReplaceText;
myNextStoryFind.Wrap = word.WdFindWrap.wdFindContinue;
myNextStoryFind.Execute(Replace: word.WdReplace.wdReplaceAll);
nextStoryRange = nextStoryRange.NextStoryRange;
}
}
app.Documents.Save();
app.Documents.Close();
}
}
}
I think you can try something like this:
var doc = app.Documents.add(path.GetFullPath(#"Docs/yourDoc.docx")), visible: false);
doc.Activate();
String textToReplace = "your text";
var selected = app.Selection;
selected.Text = string.Format("[{0}]", keyword);
selected.Find.Execute(Replace: WdReplace.wdReplaceNone);
selected.Range.Select();
var imgPath = Path.GetFullPath(string.Format(yourImage))
selected.InLineShapes.AddPicture(FileName: imgPath, LinkToFile: false, SaveWithDocument: true);
doc.SaveAs(path.GetFullPath(#"Docs/yourDoc.docx"));

ObjectARX read/write .dwg files that are not currently opened in autocad

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);
}
}
}

Categories