Disable Save functionality in Excel with VBA through C# - c#

I got one function where I need to protect the Excel file uploaded in server where it can't be edited or even saved.
To achieve this, I programmatically secure the file and added some of VBA code limit what user can do with it.
The VBA code function suppose to have 2 functionality where it can hide the Ribbon and prevent Save/SaveAs function.
You may refer into my code where I got 3 version of VBA code inside but the most desired is the no.3 of VBA code inside it.
This is my function for that purpose where I will pass the file location in string to this function.
I wish someone can assist me on how to allow the program to save the secured Excel file (using VBA code no.3).
From what I understand, I can't save it due to the VBA code on Save(not SaveAs) part won't allow this line wbkExcel.Save() to proced.
You may test the VBA code in your Excel file see if it's working or not (tested working for me so far...)
Thanks in advance everyone...
protected void ExcelEncryptor(string strExcelFile)
{
Microsoft.Office.Interop.Excel.Application wAppExcel = new Microsoft.Office.Interop.Excel.Application();
wAppExcel.Interactive = false;
wAppExcel.Visible = true;
wAppExcel.DisplayAlerts = false;
wAppExcel.AutomationSecurity = Microsoft.Office.Core.MsoAutomationSecurity.msoAutomationSecurityForceDisable;
Microsoft.Office.Interop.Excel.Workbook wbkExcel = wAppExcel.Workbooks.Open(strExcelFile.ToString(),System.Reflection.Missing.Value,System.Reflection.Missing.Value,System.Reflection.Missing.Value,System.Reflection.Missing.Value,System.Reflection.Missing.Value,System.Reflection.Missing.Value,System.Reflection.Missing.Value,System.Reflection.Missing.Value,System.Reflection.Missing.Value,System.Reflection.Missing.Value,System.Reflection.Missing.Value,System.Reflection.Missing.Value,System.Reflection.Missing.Value,System.Reflection.Missing.Value);
string strVBCode = string.Empty;
//To hide Ribbon only
/*strVBCode = "Private Sub Workbook_Open()\r\n" +
" msgbox \"This document is protected!\"\r\n" +
" application.ExecuteExcel4Macro \"show.toolbar(\"\"Ribbon\"\",False)\"\r\n" +
"End Sub";*/
//To hide Ribbon + Disable SaveAs (F12 key) but still can Save (Ctrl+S key)
/*strVBCode = "Private Sub Workbook_Open()\r\n" +
" msgbox \"This document is protected!\"\r\n" +
" application.ExecuteExcel4Macro \"show.toolbar(\"\"Ribbon\"\",False)\"\r\n" +
"End Sub\r\n" +
"Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)\r\n" +
" If (SaveAsUI = True) Then\r\n" +
" msgbox \"You are not allowed to save this document!\"\r\n" +
" Cancel = True\r\n" +
" End If\r\n" +
"End Sub";*/
//To hide Ribbon + Disable SaveAs (F12 key) and cannot Save (Ctrl+S key)
strVBCode = "Option Explicit\r\n" +
"Dim SaveByCode As Boolean\r\n" +
"Const msg As String = \"You are not allowed to save this document!\"\r\n" +
"Const ttl As String = \"This document is protected!\"\r\n" +
"Private Sub Workbook_Open()\r\n" +
" MsgBox msg, vbExclamation, ttl\r\n" +
" application.ExecuteExcel4Macro \"show.toolbar(\"\"Ribbon\"\",False)\"\r\n" +
"End Sub\r\n" +
"Private Sub Workook_BeforeClose(Cancel As Boolean)\r\n" +
" If Me.Saved = False And SaveByCode = False Then\r\n" +
" MsgBox msg, vbExclamation, ttl\r\n" +
" Cancel = True\r\n" +
" End If\r\n" +
"End Sub\r\n" +
"Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)\r\n" +
" Application.EnableEvents = False\r\n" +
" If SaveByCode = True Then\r\n" +
" SaveThisFile\r\n" +
" Else\r\n" +
" MsgBox msg, vbExclamation, ttl\r\n" +
" Cancel = True\r\n" +
" End If\r\n" +
" Application.EnableEvents = True\r\n" +
"End Sub\r\n" +
"Sub SaveThisFile()\r\n" +
" SaveByCode = True\r\n" +
" ThisWorkbook.Save\r\n" +
"End Sub";
Microsoft.Vbe.Interop.VBProject vbMacro = wbkExcel.VBProject;
Microsoft.Vbe.Interop.VBComponent vbCode = vbMacro.VBComponents.Item("ThisWorkBook");
Microsoft.Vbe.Interop.CodeModule vbModule = vbCode.CodeModule;
vbModule.AddFromString(strVBCode.ToString());
wbkExcel.Protect("Pa$$w0rd!", true, false);
foreach (Microsoft.Office.Interop.Excel.Worksheet wstExcel in wAppExcel.Worksheets)
{
wstExcel.Protect("Pa$$w0rd!", true, true, true, true, false, false, false, false, false, false, false, false, true, true, false);
}
wbkExcel.Save();
wbkExcel.Close(System.Reflection.Missing.Value,System.Reflection.Missing.Value,System.Reflection.Missing.Value);
Marshal.ReleaseComObject(wbkExcel);
Marshal.ReleaseComObject(wAppExcel);
GC.Collect();
}

After a lot of try & error of codes, I finally manage to achieve what I need, the Excel file will be protected+cannot press F12 key+cannot press Ctrl+S key+cannot press Ctrl+P key anymore, the updated VBA code also can prevent user from opening Visual Basic editor if they wish to disable the code but in my case I leave it accessible for now. Refer my updated VBA code below :
//Excel file will be password protected+cannot press F12 key+cannot press Ctrl+S key+cannot press Ctrl+P key anymore
strVBCode = "Private Sub Workbook_Open()\r\n" +
" msgbox \"This document is protected!\"\r\n" +
" application.ExecuteExcel4Macro \"show.toolbar(\"\"Ribbon\"\",false)\"\r\n" +
" ThisWorkbook.Saved = True\r\n" +
" Application.OnKey \"^s\", \"\"\r\n" +
" Application.OnKey \"^p\", \"\"\r\n" +
//Enable this line if you wish to block Visual Basic Editor
//" Application.OnKey \"%{F11}\", \"\"\r\n" +
"End Sub\r\n" +
"Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)\r\n" +
" If (SaveAsUI = true) Then\r\n" +
" msgbox \"You are not allowed to save this document!\"\r\n" +
" Cancel = True\r\n" +
" Else\r\n" +
" ThisWorkbook.Saved = True\r\n" +
" Application.OnKey \"^s\", \"\"\r\n" +
" Application.OnKey \"^p\", \"\"\r\n" +
//Enable this line if you wish to block Visual Basic Editor
//" Application.OnKey \"%{F11}\", \"\"\r\n" +
" End If\r\n" +
"End Sub";
What I notice from my previous code, command(VBA code) Cancel=True in Private Sub Workbook_BeforeSave will prevent command(C#) wbkExcel.Save() from running because the VBA code will return false for C# code in save process. I hope someone can help and correct me if I'm wrong here. Hope this one will help the others too. Thanks StackOverflow.com.

Related

Output showing System.Windows.Form.Label after every word

I am having a problem where the user enters his inputs into a text box (like a name). If the name is Jim Bob it will output like Jim System.Windows.Form.Label Bob System.Windows.Form.Label. I searched the properties tab and I am following along from the book but they do not have the same problem I have. I added some code below but I don't think it has anything to do with the problem.
string output;
output = textBoxPrefT.Text + ". " + textBoxFirstN + " " + textBoxMiddleN + " " + textBoxLastN;
labelOutput.Text = output;
You have to include .Text for all textboxes so it should look like this
string output;
output = textBoxPrefT.Text + ". " + textBoxFirstN.Text + " " + textBoxMiddleN.Text + " " + textBoxLastN.Text;
labelOutput.Text = output;

File is created but information wont save in it

Ok, so I'm new to C# and don't know what I'm doing wrong.
At the top of the button click event I have this variable:
InformationDump infodump;
infodump = new InformationDump();
After that I have the rest of the code which is meant to path to the user desktop and save whatever is filled out in the textbox's into a separate window (part of the same program):
infodump.richTextBox1.Text = textBox1.Text + ", " + textBox2.Text + ", " + textBox3.Text + ", " + textBox4.Text + ", " + comboBox1.SelectedItem;
string path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
string filename = path + "\\" + DateTime.Now.ToString("HH.mm.ss") + System.Environment.UserName + ".txt";
infodump.richTextBox1.SaveFile(filename, RichTextBoxStreamType.RichText);
Thanks in advance.
This is happening because you are creating an instance of the form (InformationDump) then try to use the RichTextBox instance but the form then will not go through the standard loading and initialization process therefore as I reproduced, the file will be created but will be empty.
It is very interesting, but if you do repeated save it works!
infodump.richTextBox1.SaveFile(filename, RichTextBoxStreamType.RichText);
// zero bytes
infodump.richTextBox1.SaveFile(filename, RichTextBoxStreamType.RichText);
// works!

Create a dropdownlist of checkboxes using EPPlus

I am using EPPlus (http://epplus.codeplex.com/) to create Excel files in my ASP.NET application. I was wondering if anyone knows if it's possible to create a dropdownlist with checkboxes in one cell. I've checked the documentation, but found nothing so far. I've also tried Googling it but haven't found anything in the right direction yet.
This question on their forum is actually a pretty good demonstration of what I'm looking for, but it hasn't received any answers: http://epplus.codeplex.com/discussions/585879
Does anyone happen to have any ideas and can point me in the right direction?
You can use:
var validationCell = sheet.DataValidations.AddListValidation("A1");
validationCell.Formula.Values.Add("a");
validationCell.Formula.Values.Add("b");
validationCell.Formula.Values.Add("c");
...
but you can choose only one single value. I think that multiple values are not supported by excel.
For others reference, here is how I could enable multiple values select:
By inserting VBA Code:
see how to do it in here , using EPPlus you can insert VBA code using something like:
package.Workbook.CreateVBAProject();
worksheet.CodeModule.Code = code;
This following code did the trick:
using (var package = new ExcelPackage(new System.IO.FileInfo("D:\\b.xlsm")))
{
ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("11");
var validationCell = worksheet.DataValidations.AddListValidation("A1");
validationCell.Formula.Values.Add("a");
validationCell.Formula.Values.Add("b");
validationCell.Formula.Values.Add("c");
string code = "Private Sub Worksheet_Change(ByVal Target As Range)\n" +
"Dim Oldvalue As String\n" +
"Dim Newvalue As String\n" +
"Application.EnableEvents = True\n" +
"On Error GoTo Exitsub\n" +
"If Target.Address = \"$A$1\" Then\n" +
" If Target.SpecialCells(xlCellTypeAllValidation) Is Nothing Then\n" +
" GoTo Exitsub\n" +
"Else: If Target.Value = \"\" Then GoTo Exitsub Else\n" +
" Application.EnableEvents = False\n" +
"Newvalue = Target.Value\n" +
"Application.Undo\n" +
"Oldvalue = Target.Value\n" +
" If Oldvalue = \"\" Then\n" +
" Target.Value = Newvalue\n" +
"Else\n" +
" If InStr(1, Oldvalue, Newvalue) = 0 Then\n" +
" Target.Value = Oldvalue & \", \" & Newvalue\n" +
"Else: \n" +
" Target.Value = Oldvalue\n" +
"End If\n" +
"End If\n" +
"End If\n" +
"End If\n" +
"Application.EnableEvents = True\n" +
"Exitsub: \n" +
" Application.EnableEvents = True\n" +
"End Sub";
package.Workbook.CreateVBAProject();
worksheet.CodeModule.Code = code;
package.Save();
}

How to know click (Ok or Cancel) event from print pop-up of web browser

In my application I am printing some data through a pop-up window. On loading the pop-up, the user will be prompted for to either print or cancel. I want to know which button is clicked (print or cancel) so that I can take some action based on the button clicked. The code and screenshot are given below.
public void Print(int Id)
{
StringBuilder sb = BadgeHelper.preparePrintableString(Id);
string printWindowFunc = "function printWindow() {\n" +
"var z = window.print();\n alert('Return: ' + z);\n" +
"checkDocumentState();\n" +
"}";
string checkDocumentStateFunc = "function checkDocumentState() {\n" +
"if (document.readyState == 'complete') {\n" +
"window.close();\n" +
"}\n" +
"else {\n alert('Else');\n" +
"setTimeout('checkDocumentState()', 2000);\n" +
"}\n"+
"}\n";
string startingHTMLCode = "<html>\n" +
"<head>\n" +
"<script type='text/javascript'>\n " +
checkDocumentStateFunc +
"\n" +
printWindowFunc +
"</script>\n " +
"</head>\n" +
"<body onload='printWindow();'>\n";
sb.Insert(0, startingHTMLCode);
sb.Append("\n</body>\n</html>");
Response.Write(sb.ToString());
}

window.focus() of JavaScript not working on IE9

This is my code
protected void LoginButton_Click(object sender, EventArgs e)
{
if (DAL.DAOKullanici.Login(KullaniciTextBox.Text,SifreTextBox.Text))
{
VeriyazPROTicari.Sessionlar.Variables.loginkontrol = true;
Session["kullaniciAdi"] = KullaniciTextBox.Text;
Session["kullaniciId"] = DAL.DAOKullanici.GetEntity(DAL.DAOKullanici.KullaniciAdiIleKullaniciIdCek(KullaniciTextBox.Text)).ID;
bool main_window_open = false;
if (!main_window_open)
{
Page.RegisterClientScriptBlock("Main_Window", "<script>" +
"var newwindow; " +
"newwindow = window.open('" + "/dashboard/dashboard.aspx" + "', 'main_app_window', ' toolbar=0,location=0,directories=0,status=1,menubar=0,left=1,top=1,scrollbars=" + "1" + ",resizable=1,width=" + "1280" + ",height=" + "800" + "'); " +
"if (window.focus) " +
"{newwindow.focus();} "
+ "</script>");
main_window_open = true;
}
HataLabel.Text = "";
}
else
{
HataLabel.Text="Hatalı Giriş";
}
}
I have no problem with it except the JavaScript part.
What I am trying to is after LoginButton is clicked opening dashboard.aspx and setting focus on it.And this code opens dashboard.aspx and sets focus in Google Chrome and Mozilla Firefox 4.However,when I try it on IE9 dashboard.aspx is opened but focus does not work and dashboard.aspx remains under the login page.
How can I set focus on a new window on IE9?
I have had a similar problem to this and it seemed to happen because in IE9 (and any IE) that the focus() method is run before the window is rendered.
To get round this there are two ways that I can see that will fix this:
Set a timer to load the focus after a small amount of time.
Defer the JavaScript from being read until the window is fully rendered.
The timer method to me is not my preferred choice as in my personal opinion it is messy and if the page takes longer to load than the timer you are stuck with the same problem. To implement the timer you could use something like:
Page.RegisterClientScriptBlock("Main_Window", "<script>" +
"setTimeout(function() { " +
"var newwindow; " +
"newwindow = window.open('" + "/dashboard/dashboard.aspx" + "', 'main_app_window', ' toolbar=0,location=0,directories=0,status=1,menubar=0,left=1,top=1,scrollbars=" + "1" + ",resizable=1,width=" + "1280" + ",height=" + "800" + "'); " +
"if (window.focus) " +
"{newwindow.focus();} " +
"}, 5);" +
"</script>");
I have set a delay of 5 seconds, which may be overkill.
The defer method is my preferred choice as I feel it is cleaner and simpler, but it may or may not work:
Page.RegisterClientScriptBlock("Main_Window", "<script type="text/javascript" defer="defer">" +
"var newwindow; " +
"newwindow = window.open('" + "/dashboard/dashboard.aspx" + "', 'main_app_window', ' toolbar=0,location=0,directories=0,status=1,menubar=0,left=1,top=1,scrollbars=" + "1" + ",resizable=1,width=" + "1280" + ",height=" + "800" + "'); " +
"if (window.focus) " +
"{newwindow.focus();} "
+ "</script>");
After what seemed like an eternity, my colleague figured out a way to make it work for us.
There are other references to the issue itself, http://social.msdn.microsoft.com/Forums/en-US/iewebdevelopment/thread/a250c431-9f09-441c-9b78-af067233ed78 http://support.microsoft.com/kb/979954
That said, we simply put the window.focus() in the body tag of the new (pop-up) page.
<body onload="FocusWindow()">
Defined FocusWindow() in a separate .js file as follows,
function FocusWindow() {
window.focus();
}

Categories

Resources