EDIT: There's a further detail I left out with my original post. The program is using a template stream rather than a concrete template for the ".Open" command. The template stream gets initialized with this code block:
public void Initialize(Stream templateStream)
{
spreadsheet = SpreadsheetDocument.Open(templateStream, true);
}
I'm still researching this, but does anyone know the implications of using a stream for the HeaderFooter object in OpenXML?
I'm new to OpenXML and still in the process of reading and learning what I can of this massive SDK. I've inherited a C# MVC.NET program that uses OpenXML to display information on an Excel spreadsheet and all of that is working, but I now need to add a footer to the same spreadsheet and I'm hitting some brick walls in my OpenXML knowledge.
I put the footer information I wanted into the spreadsheet, opened it up with the Open XML SDK Productivity Tool and found this code under <.x:oddFooter(OddFooter):
// Creates an OddFooter instance and adds its children.
public OddFooter GenerateOddFooter()
{
OddFooter oddFooter1 = new OddFooter();
oddFooter1.Text = "&L&\"Times New Roman,Regular\"Page &P of &N&C&\"Times New Roman,Regular\"Generated On: <Date/Time> Central&R&\"Times New Roman,Regular\"Report";
return oddFooter1;
}
And this code one level up under <>x:headerFooter(OddFooter):
// Creates an HeaderFooter instance and adds its children.
public HeaderFooter GenerateHeaderFooter()
{
HeaderFooter headerFooter1 = new HeaderFooter();
OddFooter oddFooter1 = new OddFooter();
oddFooter1.Text = "&L&\"Times New Roman,Regular\"Page &P of &N&C&\"Times New Roman,Regular\"Generated On: <Date/Time> Central&R&\"Times New Roman,Regular\"Report";
headerFooter1.Append(oddFooter1);
return headerFooter1;
}
Now I of course need to append the footer info somewhere, and this is where I'm stuck. In <>x:worksheet(Worksheet) I see this line of code:
worksheet1.Append(headerFooter1);
This looked easy enough, but when I looked back at the application code I found no worksheet object to append to. I thought I was close with the following line of code:
spreadsheet.WorkbookPart.Workbook.Append(headerFooter1);
but this yielded nothing. In the application I see a SpreadsheetDocument object and references to OpenXMLParts... do I need to get a spreadsheet part to append to? Or do I need to take a different approach with a Spreadsheet versus a worksheet object? Do I need to materialize the current worksheet and then append?
I have a feeling this has an easy solution, but as I said I'm still learning the SDK.
Thank you!
For those who don't know about the productivity tool, it is included with the SDK and can be downloaded from https://www.microsoft.com/en-us/download/details.aspx?displaylang=en&id=5124
On my 64 bit machine, the install path to the tool was:
"C:\Program Files (x86)\Open XML SDK\V2.0\tool\OpenXmlSdkTool.exe"
You should be able to manually add a footer to a spreadsheet, and open it up with the tool and see the exact C# required to create the entire spreadsheet, including the footer. You can then remove the parts of the code that are unnecessary, like some of the styles that are automatically added.
Related
I saw a discussion here about displaying a RTF file in a rich text edit control. Maybe what I am trying to do it too much.
In my dialog class I define a static method:
static DWORD CALLBACK MyStreamInCallback(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG* pcb)
{
std::ifstream* pFile = (std::ifstream*)dwCookie;
pFile->read((char*)pbBuff, cb);
return 0;
}
In my dialog OnInitDialog class I try to display the data:
std::ifstream File("d:\\RevisionHistoryTest.rtf");
EDITSTREAM es = { 0 };
es.dwCookie = (DWORD)&File;
es.pfnCallback = MyStreamInCallback;
::SendMessage(m_rtfEdit, EM_STREAMIN, SF_RTF, (LPARAM)&es);
Now, here is a link to a sample project. I don't know where I can put this project in the long term, but my DropBox will do for now. The project does not include the RTF file. This is how I created it:
I went to the following URL in a browser.
I selected all the Revision History content and pasted it into a Microsoft Word file.
I copied the Microsoft Word content and pasted it into a WordPad session and saved it.
Example:
Interestingly, when I subsequently open my RTF file in WordPad I get a popup message:
If I select Unblock then it still opens in the editor. I assume that is because all of the images must still be linked to those on my website. And I think this is related to the issue with my test project, because this is what I see:
I get no errors or anything. It just reads the first line and stops.
I am trying to find the easiest way to display my HTML history in a RTF window.
My original intention was to use a CHtmlView control instead (makes sense to do that) and directly read my Revision History file from the internet. But my help system is designed to permanently show the contents pane on the left. This is why I thought that RTF might be a suitable alternative. But struggling with it.
Update
Based on the comments made about 64 bit builds I located this tutorial which works for both 32 bit and 64 bit. They both display "Revision History" only.
BOOL FillRichEditFromFile(HWND hwnd, LPCTSTR pszFile)
{
BOOL fSuccess = FALSE;
HANDLE hFile = CreateFile(pszFile, GENERIC_READ,
FILE_SHARE_READ, 0, OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
EDITSTREAM es = { 0 };
es.pfnCallback = MyStreamInCallback;
es.dwCookie = (DWORD_PTR)hFile;
if (SendMessage(hwnd, EM_STREAMIN, SF_RTF, (LPARAM)&es) && es.dwError == 0)
{
fSuccess = TRUE;
}
CloseHandle(hFile);
}
return fSuccess;
}
And in OnInitDialog:
FillRichEditFromFile(m_rtfEdit.GetSafeHwnd(), _T("d:\\RevisionHistoryTest.rtf"));
But my initial issue still remains.
Update
I had forgotten to set the control to multiline! That was part of the issue:
At least all of the text is visible now. Just not the images. And I don't like the way some of the links are displayed.
I have been able to edit the file and bring the indents over to the left to make it look better. But images still won't show.
Update
As a workaround to this I realised that I could simply duplicate my HTML Revision History as a standalone page. Then I can use CHtmlView:
The benefit is that the display is consistent wit what the user sees in the help system.
I'm trying to invoke browser control in a Window Form using ChromiumFX framework in the Excel VSTO Addin.
The excel application throws the following alerts and another excel instance gets started.
Sorry, we couldn't find Files\Microsoft.xlsx. Is is possible it was removed, renamed of deleted ?
Sorry, we couldn't find Office\root\Office16\debug.log. Is is possible it was removed, renamed of deleted ?
Although I’m able to load the URL in the Web Browser control but i get the above errors multiple time and every time another instance of excel gets initiated.
I’m invoking the following piece of code after which the alerts start appearing.
var assemblyDir = System.IO.Path.GetDirectoryName(new System.Uri(System.Reflection.Assembly.GetExecutingAssembly().EscapedCodeBase).LocalPath);
Environment.CurrentDirectory = System.IO.Path.Combine(assemblyDir, #".");
if (CfxRuntime.PlatformArch == CfxPlatformArch.x64)
CfxRuntime.LibCefDirPath = #"cef\Release64";
else
CfxRuntime.LibCefDirPath = #"cef\Release";
Chromium.WebBrowser.ChromiumWebBrowser.OnBeforeCfxInitialize += ChromiumWebBrowser_OnBeforeCfxInitialize;
ChromiumWebBrowser.OnBeforeCommandLineProcessing += ChromiumWebBrowser_OnBeforeCommandLineProcessing;
Chromium.WebBrowser.ChromiumWebBrowser.Initialize();
Any suggestions on what i might be doing wrong ? Or what piece of code i’m missing ?
Since, I could not find any satifying answer on the web for this question, I put forth it in Stackoverflow. I use activexscript to manipulate Excel, Outlook. But, even after I runexcelobj.Quit() at the end, I see an EXCEL.EXE still running in the task manager.
I tried using excelobj.Application.Quit() (as mentioned by some post in stackoverflow)also did not resolve the problem.
Can somebody help me with this??
Here's one way the application goes away in JScript:
// WScript.CreateObject for cscript.exe or wscript.exe
var excel = new ActiveXObject("Excel.Application");
// ...
excel.Quit();
// null out EVERY reference to Excel objects
excel = null;
CollectGarbage();
I have a document library setup to recieve emails. The emails coming in have a single picture and a csv file which I use for some processing.
The override emailrecieved works perfectly but of course as I override I lose the nice SharePoint functionaliy that saves the incomming email as configured in the settings.
It was my understanding that I could call MyBase.EmailRecieved in my event for the underlying functionality to still work. This however is not working and no record of the email coming in is getting retained.
For now I am explicitly creating an audit trail but I would like to rely on SharePoints existing functionality as I believe it will be more robust.
What am I doing wrong with the MyBase.EmailRecieved call? Or what can I do instead if this doesnt work?
Thanks in advance.
When writing your own EmailReceived event receiver you will loose the default functionality.
What you will have to do is to implement this default functionality yourself. Let me give you a simple example. The following example saves all mail attachments to the list if they are *.csv files. You can do the same with the emailMessage and save it to the list as well. As you can see it is as easy as to add Files.Add to add a file to a document library.
public override void EmailReceived(SPList list, SPEmailMessage emailMessage, string receiverData)
{
SPFolder folder = list.RootFolder;
//save attachments to list
foreach (SPEmailAttachment attachment in emailMessage.Attachments)
{
if (attachment.FileName.EndsWith(".csv"))
{
var attachmentFileName = attachment.FileName;
folder.Files.Add(folder.Url + "/" + attachmentFileName, attachment.ContentStream, true);
}
}
list.Update();
}
Ok, you know how in programs like Microsoft Excel, or Adobe Acrobat Reader you can click on a file in explorer and it will open with the associated program. That's what I want my application to do. Now, I know how to set up the file associations in Windows so that it knows the default program for each extension. My question is how do I get my application to open the file when I double click the file.
I've searched the web using google, I've searched the msdn site, and I've searched several forums including this one but I haven't found anything that explains how to accomplish this. I'm guessing it has something to do with the parameters of the main method but that's just a guess.
If someone can point me in the right direction I can take it from there. Thanks in advance for your help.
Shane
Setting up the associations in windows will send the filename to your application on the command line.
You need to read the event args in your applications main function in order to read the file path and be able to open it in your application.
See this and this to see how to access the command line arguments in your main method.
static void Main(string[] args)
{
System.Console.WriteLine("Number of command line parameters = {0}", args.Length);
foreach (string s in args)
{
System.Console.WriteLine(s);
}
}
When you open the file, with associations set as you described, your application will be started with the first argument containing the filepath to your file.
You can try this out in a simple way by printing out the args from your main method, after you open your application by clicking on the associated file. The 0th element should be the path to your file.
Now, if you successfully reached this point, the all you need to do now is read the contents of the given file. I'm sure you'll find more than plenty of resources here on how to do that.
I guess this is what you are looking for:
FileInfo fi = new FileInfo(sfd.FileName); //the file you clicked or saved just point
//to the right file location to determine
//full filename with location info
// opening file
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = #fi.FullName;
startInfo.WindowStyle = ProcessWindowStyle.Normal;
Process process = new Process();
process.StartInfo = startInfo;
process.Start();
You will need to create registry-keys for your file-extension. This page describes well, which keys you'll need to set (see «3. How do I create file associations?»).