>Actual code might be useful......
Sure. Enjoy, if that's the word :)
This was the problem:
>>I prepare a table in Excel within a Using () statement. At the end I UsedRange.Copy() to what I understand is the clipboard. Then I Selection.PasteExcelTable in a Word document.
>>I get an COM Exception "command failed".
>>When I activate the word document and press Ctrl+V the table gets copied.
>>I wonder if that has something to do with the fact that maybe I must reactivate the Word document in code.
>>The word document gets created also within a Using() statement. I execute the Excel procedure from within the Using(Word) statement.
>>
>>I tried the Activate method of the Word.Application object and also when I wait for 5 seconds after the Activate().
The method that opens Word. Test_ComputeTotalDifference() is a method that calls Excel (see below). AddClopboard (see below) is the statement that breaks.
public static void Test_Word()
{
Test_ComputeTotalDifference();
using (var w = new WordWrapper())
{
w.App.Visible = true;
w.Doc = w.Docs.Add();
w.Sel = w.App.Selection;
w.SetNarrowMargins();
w.Title("Inventory Monitor (PIMON)");
w.Heading2("1. Overall Discrepancies");
w.AddClipboard();
w.Heading2("2. Carat Discrepancies");
w.Doc.SaveAs(@"C:\docs\WordTest.docx");
}
}
The code breaks here (a method of WordWrapper, see below
public void AddClipboard()
{
App.Activate();
System.Threading.Thread.Sleep(5000);
Sel.PasteExcelTable(false,false, false);
var t = Sel.Tables[Sel.Tables.Count];
t.Range.Select();
Sel.set_Style(App.ActiveDocument.Styles["No Spacing"]);
t.AutoFitBehavior(Word.WdAutoFitBehavior.wdAutoFitContent);
Doc.Paragraphs.Add().Range.Select();
Sel.set_Style(App.ActiveDocument.Styles["No Spacing"]);
Sel.TypeText("\n");
}
Here's the method that creates the excel sheet and copies it to the clipboard
public static void Test_ComputeTotalDifference()
{
Serialization.Deserialize();
using (var xl = new ExcelWrapper())
{
xl.wb = xl.wbs.Add();
xl.ws = xl.wb.ActiveSheet;
... snip ...
xl.ws.UsedRange.CopyPicture();
}
}
Here's the excelwrapper class that gets initialized with a Using
public class ExcelWrapper : IDisposable
{
public enum Formats {decimal2,decimal0,date,text}
public Excel.Application app;
public Excel.Workbooks wbs;
public Excel.Workbook wb;
public Excel.Worksheets wss;
public Excel.Worksheet ws;
public Excel.Range rng;
public bool mustQuit = true;
CultureInfo originalCulture;
Thread thread;
bool disposed = false;
#region "Dispose"
public ExcelWrapper()
{
thread = Thread.CurrentThread;
originalCulture = thread.CurrentCulture;
app = new Excel.Application();
app.DisplayAlerts = false;
wbs = app.Workbooks;
}
void releaseObject(object o)
{
if (o == null)
{
return;
}
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(o);
}
public void Dispose() {
if (disposed){
return;
}
if (mustQuit) {
app.Quit();
}
releaseObject(rng);
releaseObject(ws);
releaseObject(wss);
releaseObject(wb);
releaseObject(wbs);
thread.CurrentCulture = originalCulture;
disposed = true;
}
~ExcelWrapper()
{
Dispose();
}
Similarly here is the Wordwrapper.
public WordWrapper()
{
thread = Thread.CurrentThread;
App = new Word.Application();
App.DisplayAlerts = Microsoft.Office.Interop.Word.WdAlertLevel.wdAlertsNone;
Docs = App.Documents;
}
void releaseObject(object o)
{
if (o == null)
{
return;
}
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(o);
}
public void Dispose()
{
if (disposed)
{
return;
}
if (MustQuit)
{
App.Quit();
}
releaseObject(Doc);
releaseObject(Docs);
disposed = true;
}
~WordWrapper()
{
Dispose();
}
If things have the tendency to go your way, do not worry. It won't last. Jules Renard.