How to prevent SaveAs dialog in Word in C#? - c#

I am developing a custom ribbon in Microsoft Word document. I intend to override the save functionality by disabling it and save the document programmatically.
I have added DocumentBeforeSave event Handler to save the document. Here is the part of the code to save the document
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
Globals.ThisAddIn.Application.DocumentBeforeSave += new Word.ApplicationEvents4_DocumentBeforeSaveEventHandler(this.Application_DocumentBeforeSave);
}
public void Application_DocumentBeforeSave(Word.Document document, ref bool saveAsUI, ref bool cancel)
{
String destFolder = #"D:\report\tempFolder\";
Random rnd = new Random();
String fileName = "Temp_" + rnd.Next(1000, 9999).ToString() + ".docx";
var destFile = System.IO.Path.Combine(destFolder, fileName);
document.SaveAs2(destFile);
}
Any idea how to do that?

Be aware, you are trying to save the document by calling the SaveAs2 method in the DocumentBeforeSave event handler. Calling the SaveAs2 method triggers the DocumentBeforeSave method, so you will get a recursion and your dialog will never be displayed.
How to prevent SaveAs dialog in Word in C#?
In the DocumentBeforeSave event handler you may set up the saveAsUI parameter which is true if the Save As dialog box is displayed, whether to save a new document, in response to the Save command; or in response to the Save As command; or in response to the SaveAs or SaveAs2 method.

Related

Previewing a PDF in C#

I would like to create a PDF document with iTextSharp and preview it directly in the application.
And this not only once, but as often as I like, during runtime, when the user makes changes to the text input.
So far it works, but as I said before only once, when the program is started.
When I try to generate the PDF file again, I get an error message,
that the process cannot access the saved PDF document because it is currently being used by another process.
I have already tried to prevent access, but without success so far.
private void CreateDocument()
{
//my attempt to stop the browser from blocking the file acces
if (browser.IsBusy())
{
browser.Stop();
}
doc = new Document(PageSize.A4);
writer = PdfWriter.GetInstance(doc, new FileStream("document.pdf", FileMode.Create));
doc.Open();
cb = writer.DirectContent;
//here is the actual pdf generation
doc.Close();
//this is the part where I set the pdf document reference from the web browser
browser.Navigate(#"path\document.pdf");
}
The actually error occurs where I set the PDFwriter instance.
I've found a page preview component in the toolbox from iTextSharp, but sadly no reference on how to use it. Using that might work easier than trying it with the web browser.
If you don't mind a little bit of flickering just navigate to "about:blank" before you try to save.
If you have a probelm with that, just make a temporary copy of the file and open the copy with the browser. Probably not the best solutions, but should work
My problem was, that the web browser navigation is asynchronous.
As a workaround I used an event listener that keeps track, when the browser actually loaded the document.
For more information about that topic check this question out: https://stackoverflow.com/a/583909/12178103
Down here you can see my complete code
//gets called when the application starts
public Form1()
{
InitializeComponent();
//first time the web browser load operation gets called - make sure to set the event handler
webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(WebBrowserUnload);
WebBrowserLoad();
}
//this button regenerates the pdf
private void Button_Click(object sender, EventArgs e)
{
WebBrowserLoad();
}
//creates the actually pdf document
private void WebBrowserLoad()
{
browser.Hide();
browser.Navigate("about:blank");
}
private void WebBrowserUnload(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (e.Url.ToString() == "about:blank")
{
doc = new Document(PageSize.A4);
using (fileStream = new FileStream("document\pdf", FileMode.Create))
{
using (writer = PdfWriter.GetInstance(doc, fileStream))
{
PageEventHelper pageEventHelper = new PageEventHelper();
writer.PageEvent = pageEventHelper;
doc.Open();
cb = writer.DirectContent;
//create the pdf here
writer.Flush();
doc.Close();
doc.Dispose();
}
}
browser.Navigate(#"path\document.pdf");
}
else if (e.Url.ToString() == "file:///path/document.pdf")
{
browser.Show();
}
}

Statements execute but do not append text to the TextBox

I have created a C# WPF app. It takes an URL input from a text box and shows the downloaded html in another text box on a button click. To tell the user wait till the webpage is downloaded, I am appending text in the very beginning.
public void urlAnalyzer()
{
// Append text to Result box
Result.AppendText("Please wait, inspecting the URL.\n");
// Initiating WebClient to download webpage
WebClient inspecter = new WebClient();
// try-catch to avoid exception in a generic way
try
{
// stroring downloaded page in savedData
savedData = inspecter.DownloadString(webpage);
// appending downloaded html in Result box
Result.AppendText(savedData);
}
catch
{
Result.AppendText("You did not enter any valid URL.");
}
}
When the urlAnalyzer() is called, Result.AppendText() goes to Result text box's event handler method,
private void Result_TextChanged(object sender, TextChangedEventArgs e)
{
}
This event method is visited every time Result.AppendText() is called, but it doesn't append the string to Result box. When the urlAnalyzer() function is fully visited, texts then appear in the Result box.
How to make the appended text appear in the text box when the append statement is executed? How to update the text box on every text append call?
WebClient.DownloadString() is executed in UI thread and blocks UI updates. Use async version of download method:
public async void urlAnalyzer()
{
// Append text to Result box
Result.AppendText("Please wait, inspecting the URL.\n");
// Initiating WebClient to download webpage
WebClient inspecter = new WebClient();
// try-catch to avoid exception in a generic way
try
{
// stroring downloaded page in savedData
savedData = await inspecter.DownloadStringTaskAsync(webpage);
// appending downloaded html in Result box
Result.AppendText(savedData);
}
catch
{
Result.AppendText("You did not enter any valid URL.");
}
}

Multiple Instances of Word Document Ribbon button disable in Word Addin Project

My task was to create a new document from a given word document and then I need to disable the custom ribbon button only in that newly created Word document ribbon. Not the active document consider here because it is getting switch when user switch it.
Currently I cannot get the new Word instance ribbon control from C# code. When I apply following, both documents are affected.
CustomRibbon ribbon = Globals.Ribbons.CustomRibbon;
ribbon.button.Enabled = false;
Something like this should work, you have to find a way to identify your document
private void MyAddin_Startup(object sender, System.EventArgs a)
{
this.Application.DocumentChange += new ApplicationEvents4_DocumentChangeEventHandler(Application_DocumentChange);
}
private void Application_DocumentChange()
{
bool enableButton = false;
if(yourdocument) // put something here that checks the document you want the button to be enable in
{
enableButton = true;
}
CustomRibbon ribbon = Globals.Ribbons.CustomRibbon;
ribbon.button.Enabled = enableButton;
}

Doubleclick on saved file open my windows form but don't pick up any saved data

I created simple program for save/open practice. Made a setup and associated my program with my own datatype, called it .xxx (for practice).
I managed to Save and Open code and data from textbox but only from my program. Double click (or enter from windows-desktop) open up my WindowsForm as it is but there is an empty textbox. I want my saved file to be opened on double click in the same condition as when I open it from my program. How to set that up??
Here is the code of simple app (cant post images but it simple - got 1 label and 1 textbox with open and save buttons):
private void ButOpen_Click(object sender, EventArgs e)
{
textBox1.Text = "";
DialogResult result = openFileDialog1.ShowDialog();
if (result == DialogResult.OK)
{
string data = Read(openFileDialog1.FileName);
textBox1.Text = data;
}
else
{//do nothing }
}
private string Read(string file)
{
StreamReader reader = new StreamReader(file);
string data = reader.ReadToEnd();
reader.Close();
return data;
}
private void ButSave_Click(object sender, EventArgs e)
{
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
saveFileDialog1.Filter = "Something|*.xxx";
DialogResult result = saveFileDialog1.ShowDialog();
string file = saveFileDialog1.FileName.ToString();
string data = textBox1.Text;
Save(file, data);
}
private void Save(string file, string data)
{
StreamWriter writer = new StreamWriter(file);
writer.Write(data);
writer.Close();
}
NOTE:
My similar question was marked as duplicate but it is not, and this question which was referenced as duplicate Opening a text file is passed as a command line parameter does not help me.It's not the same thing...
Just wanted to find out how to configure registry so windows understand and load data inside the file, or to file save data somehow so i can open it with double click.
So someone please help. If something is not clear I will give detailed information just ask on what point.
Thanks
MSDN has some information about this:
https://msdn.microsoft.com/en-us/library/bb166549.aspx
Basically you need to create an entry in the registry so that explorer.exe knows to launch your program when that file is activated (e.g. double-clicked).
Explorer will then pass the path to the file as an argument to your program.

How do i write from textBox the text to text file and read back from the file to the textBox?

This is what i did in the top of Form1:
string line;
StreamWriter w;
StreamReader sr;
Then in the constructor:
if (File.Exists(#"d:\test.txt"))
{
sr = new StreamReader(#"d:\test.txt");
line = sr.ReadToEnd();
textBox3.Text = line;
sr.Close();
sr.Dispose();
}
w = new StreamWriter(#"d:\test.txt");
Then in textBox3 Text Changed event:
private void textBox3_TextChanged(object sender, EventArgs e)
{
if (w == null)
{
w = new StreamWriter(#"d:\ircbotsettings.txt");
w.Write(line);
w.Write(textBox3.Text);
}
}
Then in Form1 Closing event and also in a button click event i added in both places:
w.Close();
w.Dispose();
In the textBox text changed event im trying to open/create the file again for writing first writing the line if any string in it then write the new text from the textBox.
The problem is when im running now the program its going automatic first to the textBox3 text changed event and throw an exception on the line:
w = new StreamWriter(#"d:\ircbotsettings.txt");
The process cannot access the file 'd:\ircbotsettings.txt' because it is being used by another process
What i want to do is:
When typing any text in the textBox in realtime it will save it to the text file.
When i exit the program and run it again read/load from the text file the text and add/put it in the textBox.
So the text file should contain each time only one string and each time when im running the program it should read/load the string back to the textBox.
No need for a StreamWriter or StreamReader, too much clutter and boilerplate.
I would suggest
txtSettings.Text = System.IO.File.ReadAllText(path_to_file);
and on the Leave or Validated event from the textbox
System.IO.File.WriteAllText(path_to_file, txtSettings.Text);
Don't write to a file on each TextChanged event, or it will write to the file on each keystroke which would prove to be a major bottleneck. Either write to the file on Leave or (Form_Closed if it's in a dialog) or use a Timer to periodically save to the file (and keep track of changes with a boolean that you set to true in the TextChanged event).

Categories