COM Exception : 0x800AC472 raised when System is Locked (Excel VSTO) - c#

I'm using a 2D array to write data to an excel range. It works as expected when the system is not in Locked State.The code looks something like this:
Range range = SetRange(); // no. of rows and columns in the selected range is equal to the no.of rows and columns in the 2D Array
object[,] data = new object[rows, columns];
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < columns; j++)
{
data[i, j] = i+j;
}
}
range.value2 = data;
The operation "range.value2 = data" gets executed without any issues when the system is not locked. However, when I lock the system and this operation is attempted, I get an exception message "Exception from HRESULT: 0x800AC472" when executing this operation.
I understand that this is a COM Exception but I don't have any idea, why is it getting raised under these circumstances. This issue only happens when my system is in locked state. Otherwise, the same piece of code works fine.
I'm currently working on Microsoft Visual Studio 2010 and Microsoft Excel 2007.

Related

How do I assign a 2 dimensional object[,] array the value of an Excel Interop Range.Value?

I am trying to assign a 2 dimensional object array to the value of an Excel interop Range.Value
I pull the 2 object dimensional array directly from the Range.Value of the UsedRange then do some changes to the data and put it back in as a 2 dimensional object[,].
When I save the workbook either as a copy or the original the new values I assign to the Range do not persist.
Here is my code:
/// <summary>
/// Writes the data from this excel document to <see cref="ExcelDoc.FilePath"/>
/// </summary>
/// <param name="newFilePath">used to specify a new file path</param>
/// <remarks>This will overwrite any data in the file</remarks>
public void WriteDataToExcelInterop(string newFilePath = "")
{
Excel.Application exApp = new();
GetWindowThreadProcessId(exApp.Hwnd, out int excelProcessId);
Process excelProcess = Process.GetProcessById(excelProcessId);
try
{
exApp.DisplayAlerts = false;
exApp.AutomationSecurity = MsoAutomationSecurity.msoAutomationSecurityForceDisable;
Excel.Workbook workbook = exApp.Workbooks.Open(FilePath);
for (int i = 1; i <= workbook.Worksheets.Count; i++)
{
Excel.Worksheet worksheet = workbook.Worksheets[i];
string name = worksheet.Name;
Excel.Range range = worksheet.UsedRange;
for (int j = 0; j < Worksheets.Count; j++)
{
if (Worksheets[j].Name == name)
{
range.Value = Worksheets[j].DataObjects; //this does not work
range.Formula = Worksheets[j].FormulaObjects; //this does work
}
}
}
if (newFilePath == "")
{
workbook.Close(true, FilePath);
exApp.Quit();
excelProcess.Kill();
}
else
{
workbook.SaveCopyAs(newFilePath);
workbook.Close(false, FilePath);
exApp.Quit();
excelProcess.Kill();
}
}
catch (Exception ex)
{
exApp.Quit();
GC.Collect();
GC.WaitForPendingFinalizers();
excelProcess.Kill();
ExceptionHandling.ExceptionData exData = new(ex);
MessageBox.Show(exData.FormatedMessage);
}
}
I thought maybe it had something to do with the fact that the UsedRange is ReadOnly according to documentation but the fact that I can change the formulas just fine says otherwise.
So I thought maybe it had to do with the datatype going into the variable so I tried changing the datatype of DataObjects but that did also not work.
I also thought maybe the line exApp.AutomationSecurity = MsoAutomationSecurity.msoAutomationSecurityForceDisable; was causing an issue with saving since this particular excel file is macro enabled. I commented out the line but this did nothing.
I'm thinking maybe the issue is Range.Value is not changing after save because some flag somewhere has not been raised properly.
I could really use a fresh set of eyes on this to see if I'm missing something.
I found what the issue was.
I assumed wrongly that Range.Value and Range.Formula were considered separate but when I make changes to Range.Formula it overwrites any changes I made to Range.Value since I am modifying Value BEFORE Formula. I will now have to change my code a little to account for this but my code was working as intended I just didn't realize why I was getting the results I was. Hopefully this can be helpful to anyone confused by this interaction in the future.

Load an excel file that contains charts and insert new column using Infragistics.Documents.Excel

I would like to insert a new column in an existing file that contains charts.
It doesn't work, visual studio keeps running forever. I noticed that if I delete the charts that are in the loaded file it works just fine. A new column with data is inserted. I just don't know If I can conclude that it's because of existing charts that new columns can't be inserted.
Here is what I did :
private static void Main()
{
string outputFile = "metrics.xlsx";
Workbook workbook = Workbook.Load(outputFile);
Workbook temporary = SetIndicatorsWorkbook();
var values = new List<int>();
for(int j=0; j<12; j++)
{
values.Add((int)temporary.Worksheets["Unit & Integration Tests"].Rows[j].Cells[0].Value);
}
var worksheet = workbook.Worksheets["Unit Testing"];
var k = 9;
var count = worksheet.Rows[14].Cells.Count(cell => cell.Value!=null);
worksheet.Columns.Insert(count+1);
foreach (var value in values)
{
worksheet.Rows[k].Cells[count+1].Value = value;
k++;
}
workbook.Save(outputFile);
}
Your code seems fine, I used a random excel file that had a chart on the sheet and the code executed fine without errors. I will be able to assist further if you provide the metrics.xlsx file.

How to Export into Excel from Gridview

I have a button to Export my Gridview1 data to Excel, but when i tried the code below(which i used in C#), it gives me a compiling error. Can you help me..
Error 1: Cannot apply indexing with [] to an expression of type 'System.Web.UI.WebControls.GridView'
Error 2: The name 'MessageBox' does not exist in the current context
try
{
Microsoft.Office.Interop.Excel.Application excel = new Microsoft.Office.Interop.Excel.Application();
excel.Visible = true;
Microsoft.Office.Interop.Excel.Workbook workbook = excel.Workbooks.Add(System.Reflection.Missing.Value);
Microsoft.Office.Interop.Excel.Worksheet sheet1 = (Microsoft.Office.Interop.Excel.Worksheet)workbook.Sheets[1];
int StartCol = 1;
int StartRow = 1;
int j = 0, i = 0;
//Write Headers
for (j = 0; j < GridView1.Columns.Count; j++)
{
Microsoft.Office.Interop.Excel.Range myRange = (Microsoft.Office.Interop.Excel.Range)sheet1.Cells[StartRow, StartCol + j];
myRange.Value2 = GridView1.Columns[j].HeaderText;
}
StartRow++;
//Write datagridview content
for (i = 0; i < GridView1.Rows.Count; i++)
{
for (j = 0; j < GridView1.Columns.Count; j++)
{
try
{
Microsoft.Office.Interop.Excel.Range myRange = (Microsoft.Office.Interop.Excel.Range)sheet1.Cells[StartRow + i, StartCol + j];
myRange.Value2 = GridView1[j, i].Value == null ? "" : GridView1[j, i].Value;
}
catch
{
;
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
Firstly, full disclosure: I'm not an expert on asp.net WebForms, so I'm reading this on a syntax basis only (not examining whether or not your actual framework usage is correct).
Error 1
To my eye, the error occurs here:
myRange.Value2 = GridView1[j, i].Value == null ? "" : GridView1[j, i].Value;
It looks like you are trying to reference GridView1 with array notation, inside a loop using variables i and j. However, look at your loops:
for (i = 0; i < GridView1.Rows.Count; i++)
for (j = 0; j < GridView1.Columns.Count; j++)
Your loops are accessing GridView1 via collections, specifically .Rows and .Columns respectively. So my assumption would be that you might need something like:
myRange.Value2 = GridView1.Rows[i].Columns[j].Value == null ? "" : GridView1.Rows[i].Columns[j].Value;
Remember, this is just a syntactic guess based on your earlier code (GridView1.Columns[j].HeaderText).
Error 2
The issue here is that the name (static class or variable) you are using, MessageBox, doesn't seem to exist at this point in the code. So I would ask:
Is the variable in scope? I.e., is it declared earlier in the try block, and has now gone out of scope in the catch?
If it's a static class, is the assembly referenced correctly? Intellisense should pick this up for you in Visual Studio, with refactor options to include a reference as a using statement above, or fully qualify the name for you.
From memory MessageBox is a static class in the WPF assemblies somewhere to do with windows forms, not as a part of ASP.NET - it is used to show a window in a desktop program. If you wish to show a message in a browser, that would be a javascript statement like:
alert("Your exception message here");
However, you will need some means of catching that Exception (ex), grabbing the text from it (ex.ToString()) and transmitting that into the page to be shown via javascript.
Last thought on that: if you are wanting to show that error, and it's as a result of a button clicked on the page, you may be intending to invoke the Export to Excel function as an AJAX call to the server. If this is the case, try returning a HTTP error code (like a 500 or something) back to the browser, and using the .fail() binder to display an appropriate client-side error. Just a suggestion :)

Could not load type 'SAS.LanguageServiceCarriageControl' from assembly

In addition to using the integration components of SAS Enterprise Edition, I am using parts of the following project I found on Github to connect with a SAS server. The goal here is to command the server to run programs on a schedule. However, the programs need to be modified each time, which is why I am attempting to trigger them to run in this manner. However, it keeps throwing an error at lang.FlushLogLines.
https://github.com/cjdinger/SasHarness
SAS.Workspace ws = server.Workspace;
List<string> results = new List<string>();
Array CCs;
Array lineTypes;
Array logLines;
int maxLines = 100;
SAS.LanguageService lang = (SAS.LanguageService)ws.LanguageService;
Array linesVar = (Array)new string[] { PROGRAM_TEXT };
lang.SubmitLines(ref linesVar);
//THROWS AN ERROR HERE
lang.FlushLogLines(maxLines, out CCs, out lineTypes, out logLines);
for (int i = 0; i < logLines.Length; i++)
{
results.Add((string)logLines.GetValue(i));
}
After a bit of research I found the following thread where it is recommended to make sure that all the required dlls are referenced in my project. The mystery here is that I do have them referenced, but the error still occurs.
http://blogs.sas.com/content/sasdummy/2013/06/09/sas-client-with-microsoft-dot-net/
Moreover, starting after the very first line, the code is no longer using SASHarness, but is using native SAS integration libraries only. The code above is also based on examples listed in the following documentation from SAS.
https://support.sas.com/documentation/cdl/en/itechwcdg/61500/PDF/default/itechwcdg.pdf (page 27-28)
Has anybody encountered an error similar to this, and if so, how did you correct it?
Strangely, fixing this error required declaring an instance for each of the assemblies that could not be loaded. I have no idea why this fixes the problem, but it works now.
SAS.Workspace ws = server.Workspace;
string wsId = ws.UniqueIdentifier;
List<string> results = new List<string>();
Array CCs;
Array lineTypes;
Array logLines;
int maxLines = 100;
SAS.LanguageService lang = (SAS.LanguageService) server.Workspace.LanguageService;
Array linesVar = (Array) new string[] { PROGRAM_TEXT };
lang.SubmitLines(ref linesVar);
//For some reason, these two declarations need to be here
SAS.LanguageServiceCarriageControl CarriageControl = new SAS.LanguageServiceCarriageControl();
SAS.LanguageServiceLineType LineType = new SAS.LanguageServiceLineType();
lang.FlushLogLines(maxLines, out CCs, out lineTypes, out logLines);
for (int i = 0; i < logLines.Length; i++)
{
results.Add((string) logLines.GetValue(i));
}

VSTO 2010 for MS Project

I am using VSTO 2010 for MS Project.Iam loading tasks from sql server.Which will be loading data row by row.It slows the performance as it is loading task one by one.has Everyone any idea about how to load data in one go.
Thanks in Advance.
don't load row by row. Load it table by table... Let your SQL-server do all the hard work-its designed to.
I am using something like below:
MSProject.Tasks mspTask = Globals.ThisAddIn.Application.ActiveProject.Tasks;
for (int i = 0; i < dsTaskList.Tables[0].Rows.Count; i++)
{
DataRow drTask = dsTaskList.Tables[0].Rows[i];
short outLevel = Convert.ToInt16(drTask["TASK_OUTLINE_LEVEL"]);
if (outLevel == 0)
{
continue;
}
mspTask.Add();
Utility.Save_UID.Add(drTask["TASK_UID"].ToString());
Utility.editText9Bycode = true;
mspTask[k].Text9 = drTask["TASK_UID"].ToString();
string strAss = "";
DataSet dsAss = WebServiceCall.GetAssignments(drTask["TASK_UID"].ToString());
}

Categories