Office.Interop.Publisher com outofmemoryexception when call via aspx.cs page - c#

I am trying to run a catalog merge on a Microsoft Publisher document when a user clicks a button on a web page. It gets an OutOfMemoryException error message. This code runs just fine in a console app. So I am wondering if there is any tricks to get it to work. I was able to do Word merge on a docx file this way, but Publisher seems to get the OutOfmemoryException immediately.
protected void genStaffIndex_Bt_Click(object sender, EventArgs e)
{
string dataSource = #"C:\Users\score\Documents\My Data Sources\(local) caraway SupportStaffView.odc";
string fileGenDir = Server.MapPath("~/HootAdmin/GenDocs");
string outputFile = Path.Combine(fileGenDir, "SupportStaffCatalog.pub");
string sourceDoc = Server.MapPath("~/HootAdmin/DocTemplates/SupportStaffCatalog.pub");
long bytes = System.Diagnostics.Process.GetCurrentProcess().WorkingSet64;
Microsoft.Office.Interop.Publisher.Application application = new Microsoft.Office.Interop.Publisher.Application();
bytes = System.Diagnostics.Process.GetCurrentProcess().WorkingSet64;
var mydoc = application.Open(sourceDoc, false, false, Microsoft.Office.Interop.Publisher.PbSaveOptions.pbDoNotSaveChanges);
mydoc.MailMerge.OpenDataSource(bstrDataSource: dataSource);
var newdoc = mydoc.MailMerge.Execute(false, Microsoft.Office.Interop.Publisher.PbMailMergeDestination.pbMergeToNewPublication);
mydoc.Close();
newdoc.SaveAs(outputFile, Microsoft.Office.Interop.Publisher.PbFileFormat.pbFilePublication, false);
newdoc.Close();
application.Quit();

Related

Excel file Modified using EPPlus is not working in Ms Excel 2007

Okay, so i have an excel file (.xlsx) which will be downloaded when user clicks a button. The file is stored in a folder and will be processed by adding data validation and such before sending it to user. In my case i'm only adding dropdowns which will be filled from another sheet.
Here is my code that generates the file:
public IActionResult DownloadTemplateExcelFile(string type)
{
string fullFilePath = "../TemplateFiles/";
string fileName = "";
if (type != "")
{
fileName = type + ".xlsx";
fullFilePath += fileName;
}
var fileData = ExcelHelper.CreateExcelFile(type, fullFilePath);
return this.File(fileData, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",fileName);
}
And this code below is the file processing:
public static class ExcelHelper{
public static byte[] CreateExcelFile(string type, string fullFilePath){
using (var package = new ExcelPackage(new FileInfo(fullFilePath))){
// Getting list of values and set it for dropdown values
// List<string> dropdown1 = .. list string is loaded from database
ExcelWorksheet sheetDropdown1 = package.Workbook.Worksheets.Add("Dropdowns1");
var mainSheet= package.Workbook.Worksheets["Sheet1"];
sheetDropdown1.Cells["A1"].LoadFromCollection(dropdown1);
var dropdown1Addr = mainSheet.Cells[3,5,300,5].Address;
var dropdown1Formula = "='Dropdowns1'!$A:$A";
var validation = mainSheet.DataValidations.AddListValidation(dropdown1Addr);
validation.ShowErrorMessage = true;
validation.ErrorStyle = OfficeOpenXml.DataValidation.ExcelDataValidationWarningStyle.stop;
validation.ErrorTitle = "An invalid value was entered";
validation.Error = "Select a value from the list";
validation.AllowBlank = true;
validation.Formula.ExcelFormula = dropdown1Formula;
validation.Validate();
var excelFile = package.GetAsByteArray();
package.Dispose();
return excelFile;
}
}
}
When i opened the file in Excel 2010+ it worked just fine, the dropdown is loaded nicely and the cells in which the data validation is applied is working. However in excel 2007 when i tried to open it showed an error need to repair if i want to open it in 2007. If i do so however, the dropdown function is lost and unusable.
I've racked my brain but still haven't found any solution yet. How can i "Fix" this? I'm using EPPlus 6 for reference.

XmlMap.Import without using Interopt

I've defined an Excel template using Xml mappings that will generate the Excel report based on the Xml that I import.
I need to generate this report on the server so I can't use Microsoft Interopt. How can I do the following (C#) with an open source library?
Application excel = new Application();
Workbook workbook = excel.Workbooks.Open(Path.Combine(Directory.GetCurrentDirectory(), "TestTemplate.xlsx"));
var result = workbook.XmlMaps[1].Import(Path.Combine(Directory.GetCurrentDirectory(), "TestData.xml"), true);
workbook.Save();
workbook.Close();
excel.Workbooks.Close();
This allows me to do formatting of the Excel sheet on my own PC (with Office 365) and then save the template and publish with the project and just update the XML data and save as a new report.
I ended up going with ClosedXML's reporting plugin that has a variable replacement function that ended up working just as well.
The example from their website:
protected void Report()
{
const string outputFile = #".\Output\report.xlsx";
var template = new XLTemplate(#".\Templates\report.xlsx");
using (var db = new DbDemos())
{
var cust = db.customers.LoadWith(c => c.Orders).First();
template.AddVariable(cust);
template.Generate();
}
template.SaveAs(outputFile);
//Show report
Process.Start(new ProcessStartInfo(outputFile) { UseShellExecute = true });
}

FileHelpers delete list/reset

I am developing a test application using C# and .NET. I am a programmer (embedded) but I am not very familiar with this environment.
I have made an application that collects sensor data from an Arduino and uses FileHelpers API to populate a list of data for exporting to CSV.
// Initializing Log generation
FileHelperEngine<logItems> engine = new FileHelperEngine<logItems>();
List<logItems> logItems = new List<logItems>();
And the log save event
private void stopButton_Click(object sender, EventArgs e)
{
tmrGUI.Enabled = false; // Stop sampling
double maxValue = pressureTable.Max();
PeakValueIndicator.Text = maxValue.ToString("0.00");
engine.HeaderText = "Sample,Pressure,Time";
engine.WriteFile(string.Concat(DateTime.Now.ToString("yyyyMMdd_HHmmss"), "_", TestNameControl.Text, ".csv"), logItems);
logGenerator();
TestNameControl.Text = string.Empty;
startButton.Enabled = false;
stopButton.Enabled = false;
The application works, however if I run the data collection more than one time without closing the program between runs it will append the new sensor data at the end of the previous data list.
Is there a way to reset the list either by using the FileHelpers API or memory resetting the list using regular C#?

Sign into a webpage using default browser c#

I am trying to create a program that can login to a website through C#, but also using the default browser.
Currently, it works with the in-form browser fine, but I can't find the code to adapt it to work in an actual browser.
Any feedback is appreciated,
using System;
using System.Windows.Forms;
using System.Diagnostics;
namespace PortalLogin2
{
public partial class Form1 : Form
{
bool mHooked;
public Form1()
{
InitializeComponent();
webBrowser1.DocumentCompleted += webBrowser1_DocumentCompleted;
}
private void button1_Click(object sender, EventArgs e)
{
string input = "https://en-gb.facebook.com/";
Process.Start(input);
}
void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (mHooked) return;
HtmlDocument doc = webBrowser1.Document;
HtmlElement username = doc.GetElementById("email");
HtmlElement password = doc.GetElementById("pass");
HtmlElement submit = doc.GetElementById("u_0_");
string txtUser = "insert username here";
string txtPass = "insert password here";
doc.GetElementById("email").InnerText = txtUser.ToString();
doc.GetElementById("pass").InnerText = txtPass.ToString();
submit.InvokeMember("click");
mHooked = true;
}
}
}
Try www.seleniumhq.org
Selenium automates browsers. That's it! What you do with that power is
entirely up to you. Primarily, it is for automating web applications
for testing purposes, but is certainly not limited to just that.
Boring web-based administration tasks can (and should!) also be
automated as well.
It has support for C# and other languages.
It's possible to automate Internet Explorer by adding the COM references "Microsoft Internet Controls" and "Microsoft HTML Object Library".
Here is a working example to fill the field "email" on Facebook:
var ie = new SHDocVw.InternetExplorer();
ie.Visible = true;
// once the page is loaded
ie.DocumentComplete += (object pDisp, ref object URL) => {
// get the document
mshtml.HTMLDocument doc = (mshtml.HTMLDocument)(object)ie.Document;
// set the email field
mshtml.IHTMLElement email = doc.getElementById("email");
email.setAttribute("value", "na#na.na");
};
// naviagte to the page
ie.Navigate("https://en-gb.facebook.com/");
// wait indefinitely without blocking the current thread
new AutoResetEvent(false).WaitOne();

Can't upload to a specific folder getting 503 error

I am trying to upload a simple text file to a specific folder in google documents but with no luck.
FileStream fileStream = new FileStream(#"c:\test.txt", System.IO.FileMode.Open);
DocumentEntry lastUploadEntry =
globalData.service.UploadDocument("c:\\test.txt", null);
string feed =
"https://docs.google.com/feeds/upload/create-session/default/private/full/folder%folder:0B2dzFB6YvN-kYTRlNmNhYjEtMTVmNC00ZThkLThiMjQtMzFhZmMzOGE2ZWU1/contents/";
var result =
globalData.service.Insert(new Uri(feed), fileStream, "application/pdf", "test");
I get an error saying
"The remote server returned an error: (503) Server Unavailable."
I am suspecting that the destination folders uri is wrong but i can't figure out the correct one.
There's a complete sample at https://developers.google.com/google-apps/documents-list/#uploading_a_new_document_or_file_with_both_metadata_and_content that uses the resumable upload component:
using System;
using Google.GData.Client;
using Google.GData.Client.ResumableUpload;
using Google.GData.Documents;
namespace MyDocumentsListIntegration
{
class Program
{
static void Main(string[] args)
{
DocumentsService service = new DocumentsService("MyDocumentsListIntegration-v1");
// TODO: Instantiate an Authenticator object according to your authentication
// mechanism (e.g. OAuth2Authenticator).
// Authenticator authenticator = ...
// Instantiate a DocumentEntry object to be inserted.
DocumentEntry entry = new DocumentEntry();
// Set the document title
entry.Title.Text = "Legal Contract";
// Set the media source
entry.MediaSource = new MediaFileSource("c:\\contract.txt", "text/plain");
// Define the resumable upload link
Uri createUploadUrl = new Uri("https://docs.google.com/feeds/upload/create-session/default/private/full");
AtomLink link = new AtomLink(createUploadUrl.AbsoluteUri);
link.Rel = ResumableUploader.CreateMediaRelation;
entry.Links.Add(link);
// Set the service to be used to parse the returned entry
entry.Service = service;
// Instantiate the ResumableUploader component.
ResumableUploader uploader = new ResumableUploader();
// Set the handlers for the completion and progress events
uploader.AsyncOperationCompleted += new AsyncOperationCompletedEventHandler(OnDone);
uploader.AsyncOperationProgress += new AsyncOperationProgressEventHandler(OnProgress);
// Start the upload process
uploader.InsertAsync(authenticator, entry, new object());
}
static void OnDone(object sender, AsyncOperationCompletedEventArgs e) {
DocumentEntry entry = e.Entry as DocumentEntry;
}
static void OnProgress(object sender, AsyncOperationProgressEventArgs e) {
int percentage = e.ProgressPercentage;
}
}
}
Just follow the article Google Apps Platform Uploading documents
Also check out Google Documents List API version 3.0
Uri should be something similar to below:
string feed = #"https://developers.google.com/google-apps/documents-list/#getting_a_resource_entry_again";
//it may not be exact, just check and read from the links
Try this uri:
"https://docs.google.com/feeds/default/private/full/folder%3A" + fRid + "/contents"
//fRid is the Resource Id of the folder.. in your case: 0B2dzFB6YvN-kYTRlNmNhYjEtMTVmNC00ZThkLThiMjQtMzFhZmMzOGE2ZWU1
Also I guess your URI is giving this error because you are using folder resource ID as - folder:resourceID
Try removing folder: and use only RID
Code to cutout "folder:" -
int ridIndex = dRid.IndexOf(":");
Rid = Rid.Substring(ridIndex + 1);

Categories