Delete .doc duplication during PDF conversion c# - c#

I currently have a program that merges a folder consisting of word docs into one combined file via user input with a FileBrowserDialog. Once files are selected, a 'combine' button applies the code shown below which sources the folder containing the documents, output location and name of the file created.
string fileDate = DateTime.Now.ToString("dd-MM-yy");
string fileTime = DateTime.Now.ToString("HH.mm.ss");
string outcomeFolder = outputFolder;
string outputFileType = ".docx";
string outputFile = "Combined Folder " + fileDate + " # " + fileTime + outputFileType;
string outputFileName = Path.Combine(outcomeFolder, outputFile);
// Combines the file name, output path selected and the yes / no for pagebreaks.
MsWord.Merge(sourceFiles, outputFileName, pageBreaker);
// Message displaying how many files are combined.
MessageBox.Show("A total of " + sourceFiles.Length.ToString() + " documents have been merged", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);}
The MsWord referenced calls a separate .CS file which combines the folder components, output name and a boolean to enable page-breaks. The MsWord also automatically saves the word .doc to the user specified location once the contents of the folder are successfully combined. MsWord.Merge(sourceFiles, outputFileName, pageBreaker);
The issue i'm wanting to address is, when I enable this check box:
if (convert2PDFBox.Checked)
Microsoft.Office.Interop.Word.Application officeApp = new Microsoft.Office.Interop.Word.Application();
officeApp.Documents.Open(outputFileName);
outputFileType = ".pdf";
officeApp.ActiveDocument.SaveAs(outputFileName + outputFileType, WdSaveFormat.wdFormatPDF);
officeApp.Quit();
I want the program to solely create a PDF of the combined folder and not 2 seperate .doc and .PDF files, which it currently does. Since the MsWord.save function is called separately and is essential to the overall function of my program, I was wondering is there a possibility of deleting the initially combined file once conversion of the PDF takes place? e.g. "combinedDocument".Delete - Essentially allowing the copy to take place however not presenting the user with the initial .doc - only the .PDF
Though the issue is small, I would love to get it addressed and welcome any suggestions or advice with this manner. I can also provide any additional information if needed, thank you.
tl;dr - merging program creates an amalgamated Word .doc, which i want to change solely to a PDF when a checkbox is enabled instead of creating a .doc and PDF.

I finally resolved my issue - What I decided to do was manipulate my existing MsWord.cs and create a separate PDF.cs call for my main form:
Rather than save the Word .doc when being merged, I instead used: wordApplication.ActiveDocument.SaveAs(outputFile, Word.WdSaveFormat.wdFormatPDF);
which saved the merged content thus far as a .pdf
This however presented errors with Microsoft Word as I was then prompted to 'Save File As' due to the merged file never actually being saved in a .Doc / .Docx format
I then altered the closing statement of the call,
// Close Word application
wordApplication.Quit(
false, // save changes
By setting the 'Save Changes' setting to False, it removed the 'Save As' prompt which allowed the Word doc. to be dismissed without needing to be saved, thus leaving only the initial PDF created. I then applied the two separate File type calls to each checkbox presented, which allowed the user to enable the outcome format of the merged files.
Thank you for the suggestions regarding the issue.

Related

Embedding Text File in Resources C#

I'm attempting to do two things. I want to embed a text file into my project so that I can utilise it and modify it, but at the same time I don't want to have to package it when I send the project out to users (I.E included in the exe file).
I've had a look around and there's been multiple questions already but I just cant seem to get any to work. Here's the steps I've taken so far;
Added the text file to my "Resources Folder"
Build action to "Content" and output directory to "Do not copy"
I then try to access the file in my code;
if (File.Exists(Properties.Resources.company_map_template))
{
MessageBox.Show("Test");
var objReader = new StreamReader(Properties.Resources.company_map_template);
string line = "";
line = objReader.ReadToEnd();
objReader.Close();
line = line.Replace("[latlong]", latitude + ", " + longitude);
mapWebBrowser.NavigateToString(line);
}
The MessageBox never appears which to me means that it cannot find the file and somewhere somehow I've done something wrong. How can I add the file into my project so I don't need to distribute with an exe whilst being able to access it in code?
I would use the following:
BuildAction to None (not needed)
and add your file to Resources.resx under files (using DragAndDrop from SolutionExplorer to opened Resources.resx)
Access to your Text:
using YOURNAMESPACE.Configuration.Properties;
string fileContent = Resources.company_map_template;
Then you're done. You don't need to access through StreamReader

C# OpenFileDialog open zip folder containing single file?

I have an application which currently provides the user with the ability to view a PDF file inside the application by using File->Open, browsing to the location of the PDF file using a Microsoft.Win32.OpenFileDialog, and then displaying that PDF file in a System.Windows.Controls.WebBrowser in the GUI.
I am creating the OpenFileDialog and setting the file extensions it can open using:
/*Create Open File dialog */
Microsoft.Win32.OpenFileDialog OFDlg = new Microsoft.Win32.OpenFileDialog();
/*Set filter for file extension and default file extension */
OFDlg.DefaultExt = ".pdf";
OFDlg.Filter = "PDF Documents (.pdf)|*.pdf";
I now want to extend this, so that the user can open a ZIP folder containing a single PDF document, and display that PDF document in the same way that I am above.
I tried changing the filter to allow .zip files, i.e.
OFDlg.DefaultExt = ".pdf|.zip";
OFDlg.Filter = "PDF Documents (.pdf)|*.pdf|ZIP|*.zip";
but when I browse to the location of the .zip file in the OpenFileDialog, the .zip folder is not displayed there- only normal folders and PDF documents (other documents in that directory, such as .doc & .xls are not displayed in the OpenFileDialog).
My reason for wanting to be able to open the contents of a .zip file directly from the .zip, rather than navigating to that file itself, is so that I can add public/private key encryption to the .zip, so that its contents can only be read securely.
I know that there could in theory be problems if the .zip contains more than one file, but I intend to send each encrypted file in its own zip folder, so it can be assumed that any zip file that the user is trying to open contains a single .pdf, and nothing else.
So my questions are:
How can I make .zip folders visible from the OpenFileDialog?
How can I make the selection of that .zip folder automatically open and display its contents (a single PDF file) in the System.Window.Controls.WebBrowser that I am currently using to display PDFs in my GUI?
Edit 1
I tried changing my OpenFile() method to the following code:
/*Set filter for file extension and default file extension */
OFDlg.DefaultExt = ".pdf";
OFDlg.DefaultExt = ".zip";
OFDlg.Filter = "PDF Documents (.pdf)|*.pdf";
OFDlg.Filter = "ZIP Folders (.ZIP)|*.zip";
but when I now run my application, and browse to the same location, although the .zip folder is now shown in the OpenFileDialog, the .pdf files no longer are... and if I double click the .zip folder, my application breaks, and I get a runtime error on the line
PdfPanel.OpenFile(docFP);
which says:
An unhandled exception of type 'System.AccessViolationException' occurred in MoonPdfLib.dll
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
I guess that's to do with the MoonPDF library that I'm using to read the PDFs being unable to handle the .zip extension?
How would I resolve this to be able to open the PDF inside the ZIP?
Edit 2
Ok, so I've resolved the issue about only being able to see either the PDF files or the .ZIP folders (not both at the same time), by moving the functionality into two separate methods- one to display the PDF direct from the PDF's filepath, and another to display the PDF from the path of the .ZIP folder holding it.
The method for displaying the PDFs directly currently works (it is essentially the code in the first bit of code I've quoted). However the method for displaying the PDFs from the ZIP currently doesn't work...
I understand the reason for this- it's because I am passing a .zip folder to the OpenFile method... The code for this method currently looks like this:
private void openZipMenuItem_click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog OZipDlg = new Microsoft.Win32.OpenFileDialog();
OZipDlg.DefaultExt = ".zip";
OZipDlg.Filter = "ZIP Folder (.zip)|*.zip";
Nullable<bool> result = OZipDlg.ShowDialog();
if (result == true)
{
/*Open document */
string filename = OZipDlg.FileName;
//fnTextBox.Text = filename;
zipFP = OZipDlg.FileName;
/*browser.Navigate(docFP); ERF (27/05/2016 # 0935) Comment this line- I want to use PdfPanel to open docFP, not browser */
Console.WriteLine("Panel height: " + PdfPanel.ActualHeight);
PdfPanel.OpenFile(zipFP);
}
}
When I try to call this function to open a .zip, I get a runtime exception which says:
AccessViolationException was unhandled
An unhandled exception of type 'System.AccessViolationException' occurred in MoonPdfLib.dll
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
I understand that I can't display a Zip folder in the PdfPanel (which is a MoonPdfPanel that I am using from the MoonPdfLibrary), so I know that I will get an exception here.
How can I pass the contents of zipFP to the call to PdfPanel.OpenFile(), rather than passing zipFP itself to it?
Edit 3
Ok, so my code is currently extracting the PDF file successfully from the ZIP folder when I open it- I can see that it is copied to the directory I have specified. I am now trying to get the PDF to be displayed automatically in the PDF Panel on my application- I've done this by adding the following code:
try{
string extractPath = #"C:\Documents";
using(ZipArchivev zip = ZipFile.Open(zipFP, ZipArchiveMode.Read))
foreach(ZipArchiveEntry entry in zip.Entries){
try{
ZipFile.ExtractToDirectory(zipFP, extractPath);
Console.WriteLine("zipFP: " + zipFP);
}catch(System.IOException){
Console.WriteLine("File already exists...");
}
}
string ExtractedPDF = string.Concat(extractPath, zipFP);
PdfPanel.OpenFile(ExtractedPDF);
}catch(AccessViolationException ex){
Console.WriteLine("Can't display a zip in the PDF panel..." + ex.InnerException);
}
But when my code tries to execute the line PdfPanel.OpenFile(ExtracedPDF);, I get an exception that says:
FileNotFoundException was unhandled | An unhandled exception of type 'System.IO.FileNotFoundException' occurred in MoonPdfLib.dll'
I understand that this is happening because the variable I am trying to display in the PDFPanel, ExtractedPDF actually holds the path of the folder containing the PDF, and not the PDF itself- How do I give it the name of the PDF file, when I don't actually know what the PDF file will be called?
Here is something works similar to your requests, the logic behind the code is:
Only display zip and pdf files in the OpenFileDialog
If user selected a pdf file, show it in the panel
If user selected a zip file, change the directory of the OpenFileDialog to the zip file(treat it like a folder)
Example code (working code....):
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "PDF files (.pdf)|*.pdf;*.zip";
ofd.ShowDialog();
//reopen OpenFileDialog if it is zip file. this part can be improved.
if (ofd.FileName.EndsWith(".zip"))
{
ofd.InitialDirectory = ofd.FileName;
ofd.ShowDialog();
}
//if it's a PDF, note that you don't really need this check,
//as the only file can reache here will be a PDF,
//and it can be the temporary file that inside a zip.
if(ofd.FileName.EndsWith(".pdf"))
{
//show it in your PdfPanel
}
Edit, based on your new comments and added code. you need to change your code to the following as your current code is mistaken directory with the file:
try{
string extractPath = #"C:\Documents";
string ExtractedPDF ="";
using(ZipArchivev zip = ZipFile.Open(zipFP, ZipArchiveMode.Read))
foreach(ZipArchiveEntry entry in zip.Entries){
try{
ExtractedPDF= Path.Combine(extractPath, entry.FullName);
entry.ExtractToFile(ExtractedPDF,true);
}catch(System.IOException){
Console.WriteLine("error during extraction...");
}
}
if( System.IO.File.Exists(ExtractedPDF))
{
PdfPanel.OpenFile(ExtractedPDF);
}
}catch(AccessViolationException ex){
Console.WriteLine("Can't display a zip in the PDF panel..." + ex.InnerException);
}
If you want to support multiple file formats in an open file dialog, you need to add a third (or better first) option, that aggregates all supported file extensions:
OFDlg.Filter = "Supported file formats|*.pdf;*.zip|PDF Documents|*.pdf|ZIP files|*.zip";
First, regarding showing the files in the open file dialog. Your initial method for doing this was correct. Your updated code now first sets the filter to show PDFs, then replaces that filter with one that shows zip files. The standard file open dialog isn't designed to show different file types at the same time. The right way to handle that is to give the user the option for which file types they want to show.
Typically, an "All files" option is added as well (with . as the search pattern). This way if the file type the user wants to open isn't available in the list, they can see it regardless.
As for opening the PDF file that is in the zip file, you need to take are of extracting the PDF file yourself. This question has some options for how to do that.

Save Image to word of HTML reference

I export data from my database to word in HTML format from my web application, which works fine for me , i have inserted image into record,
the document displays the image also , all works fine for me except when i save that file and send to someone else .. ms word will not find link to that image
Is there anyway to save that image on the document so path issues will not raise
Here is my code : StrTitle contains all the HTML including Image links as well
string strBody = "<html>" +
"<body>" + strTitle +
"</body>" +
"</html>";
string fileName = "Policies.doc";
//object missing = System.Reflection.Missing.Value;
// You can add whatever you want to add as the HTML and it will be generated as Ms Word docs
Response.AppendHeader("Content-Type", "application/msword");
Response.AppendHeader("Content-disposition", "attachment; filename=" + fileName);
Response.Write(strBody);
You can create your html img tag with the image data encoded with base64. This way the image data is contained in the html document it self.
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIA..." />
You images are probably only available via filesystem (i.e. their src starts with file).
There are a few ways
Make the image available via the internet: make sure their src starts with http and that they are hosted on a web server visible to the downloader (for example, the same server from which they are dowonloading the image)
Use a library, for example see NuGet
You can inline the images as #DevZer0 suggests.
Based on experience
Is the simplest to implement but has some annoyances (the server needs to be available to the user)
Is probably the best way if you do a lot of Word or Office files manipulation.
Can be done and it would solve the problem, although you wouldn't have a full library to support further use cases.
Use a word document creation library if you really want to have flexibility in creating doc or docx type files. Like all other popular document formats, the structure needs to be accurate enough for the program that opens up the documents. Like you obviously cannot create a PDF file just by setting content type "application/PDF", if your content is not in a structure that PDF reader expects. Content type would just make the browser identify the extension (incorrectly in this case) and download it as a PDF, but its actually simple text. Same goes for MS word or any other format that requires a particular document structure to be parsed and displyed properly.
Since every picture, table is of type shape in Word/Excel/Powerpoint, you could simply add with your program an AlternativeText to your picture, which would actually save a URL of the download URL and when you open, it will retrieve its URL and replace it.
foreach (NetOffice.WordApi.InlineShape s in docWord.InlineShapes)
{
if (s.Type==NetOffice.WordApi.Enums.WdInlineShapeType.wdInlineShapePicture && s.AlternativeText.Contains("|"))
{
s.AlternativeText=<your website URL to download the picture>;
}
}
This would be the C# approach, but would require more time for the picture. If you write a small software for it, which replaces all pictures which contain a s.AlternativeText, you could replace a lot of pictures at same time.
NetOffice.WordApi.InlineShape i=appWord.ActiveDocument.InlineShapes.AddPicture(s.AlternativeText, false, true);
It will look for the picture at that location.
You can do that for your whole document with the 1 loop I wrote you. Means, if it is a picture and contains some AlternativeText, then inside you loop you use the AddPicture function.
Edit: Anoter solution, would be to set a hyperlink to your picture, which would actually go to a FTP server where the picture is located and when you click on the picture, it will open it, means he can replace it by himself(bad, if you have 200 pictures in your document)
Edit according Clipboard:
string html = Clipboard.GetText(TextDataFormat.Html);
File.WriteAllText(temporaryFilePath, html);
NetOffice.WordApi.InlineShape i=appWord.ActiveDocument.InlineShapes.AddPicture(temporaryFilePath, false, true);
The Clipboard in Word is capable to transform a given HTML and when you paste it to transform that table or picture into Word. This works too for Excel, but doesn't for Powerpoint. You could do something like that for your pictures and drag and drop from your database.

Unique File Renaming Issue

I am developing an app right now that reads in data from a windows from and generates an XML file based on the input.
I am tasked with creating a new file each time the form is updated (User presses "Submit"). (so far so good)
Here is the catch: The file has to be named after a prominent field input. (If the user types '993388CX' in the text box, the app would rename the pending file 993388CX.xml).
I understand how to actually rename a file in C#, but not how to rename it based on a form's input. Do any classes/methods exist that will dynamically rename the file based on the form input?
Code:
//Reads info1 from user input on the app UI and generates XML statement
XTemp = XDoc.CreateElement("New_Info");
XTemp.InnerText = info1.Text;
Xsource.AppendChild(XTemp);
XDoc.Save(#"C:\oldfile.xml");
I need the new file to be renamed after the string in info1.Text
If the user input was "John5", the file needs renamed to john5.xml
Thank you
Either directly save it with the correct name:
XDoc.Save(String.Format("C:\\{0}.xml",info1.Text));
OR
Rename it afterwards
File.Move("c:\\oldfile.xml", String.Format("C:\\{0}.xml",info1.Text));
XDoc.Save(#"C:\" + info1.Text + ".xml");
File.Move should do what you want.

Saving the opened file in particular folder

I have a dropdownlist and a textbox. When i write some name and select some options in dropdownlist like word or excel or powerpoint, that particular file opens as an attachment and i should save it in "data" folder which is already present in the solution explorer. My code is like this
string file = TextBox1.Text;
if (dd1.SelectedIndex == 1)
{
Response.ContentType = "application/word";
Response.AddHeader("content-disposition", "attachment;filename =" + file + ".docx");
}
How can I store this file in "data" folder?
The simple answer is "you cannot". Saving file is taking place on the client side. Your web application knows nothing about the client machine (not even whether it's a real browser or another script) and has no control over the client. The end user will have to manually select data folder to save the file to.

Categories