I have opened Excel file in my C# WinForm Application adding reference to Microsoft.Office.Interop.Excel.dll and using DSO FRAMER CONTROL. But i want to open my excel file with read only protection.I have successfully done this for WORD Application like this
Word.Document wordDoc = (Word.Document)axFramerControl1.ActiveDocument;
Word.Application wordApp = wordDoc.Application;
wordDoc.Protect(Word.WdProtectionType.wdAllowOnlyReading);
In the same i want to do this work for Excel.But i couldn't able to protect Excel file on that way.
string path = "C:\\test-wb.xlsx";
axFramerControl1.Open(path, true,"excel.sheet", "", "");
Excel._Workbook excelDoc =(Microsoft.Office.Interop.Excel._Workbook)axFramerControl1.ActiveDocument;
Excel.Application excelApp =excelDoc.Application;
//What code should i write to protect Excel Workbook with read - only.
excelDoc.Protect(misval, true, misval);//It is not working.
Call theOpen method with third parameter (ReadOnly) = true.
See MSDN documentation :
ReadOnly
Optional Object. True to open the workbook in read-only mode.
The WorkBook class has a Protect method, similar (but not identical) to the one supported by Word. I can't find the COM/interop documentation, but the VSTO documentation covers the same ground, and the method signatures are the same:
Protect
Protects a workbook so that it cannot be modified.
public virtual void Protect (
[OptionalAttribute] Object Password,
[OptionalAttribute] Object Structure,
[OptionalAttribute] Object Windows
)
(This all assumes that what you wanted to achieve was to protect the document, since that's what the Word code does, as opposed to opening the document read only, which is what your narrative seems to be saying, in which case, #gdoron's answer is more suitable
Related
I want a method to write the datatable data to .xls,.xlsx or.csv based on the input provided along with the delimiter as input
public class DataTableExtensions
{
/*Input Params : Datatable input
fileFormat(.xls,.csv,.xlsx)
delimeter('\t' (tabSpace) or ,(comma) or | (pipe Symbol)
filepath - Any local folder*/
public void WriteToCsvFile(DataTable dataTable,string fileFormat,string delimeter, string filePath)
{
//Code to convert file based on the input
//Code to create file
System.IO.File.WriteAllText(filePath, fileContent.ToString());
}
}
You said it is only 1000 rows every 2 hours in the comments. That is a acceptable amount of data for a C# programm. I would say the big question left is wich output format you use.
.CSV is the simplest one. This format can be done with a File.WriteLine() and some string concaction. There is no build in CSV parser or writer code I am aware off in C#, but there is plenty of 3rd party code.
.XLS requires the (t)rusty Office COM Interop. That requires office to be installed and does not work from a non-interactive session (like a Windows Service). On top of all the normal issues for using COM interop.
There is the odd "export to XLS" function on existing classses, but those are rare, far inbetween and about everything you get. Unfortunately as we always had COM Interop as fallback, we never quite developed a standalone library for working with .XLS. Ironically working with this old format is harder from C#/.NET then it would be from Java.
.XLSX however is easier. It can be written using the OpenXML SDK. Or the XML writer and ZipArchive class: At their core all the ???x formats are a bunch of .XML files in a renamed .ZIP container. There should even be 3rd party code out there to make using the SDK easier.
.CSV is the lowest common denominator and propably the easiest to create. However if a user is supposed to open this document, the lack for formating might become an issue.
.XSLX would be my choice if you need a user to open it.
.XSL I would avoid like a swarm of angry bees.
I have written this Program to convert Xls,XLSx using console application with
Datatable as input and for text file I have written a simple stream writer logic.This works good. Initially I have installed package manage console and below code
using expertXLs package.I am not sure wheather I can share the key of that
or not.Please search the key and give in config before running it
Package Manage Console - Install-Package ExpertXls.ExcelLibrary -Version 5.0.0
Code :
--------
private static void GenerateTxtFileFromDataTable(DataTable sampleDataTable,string delimiter)
{
var _expertxlsLK = ConfigurationManager.AppSettings["ExpertxlsLK"];
//GetKey Value from config
// Create the workbook in which the data from the DataTable will be loaded 0 for 2003 Excel(xls),1 for 2007 Excel(xlsx)
ExcelWorkbookFormat workbookFormat = ExcelWorkbookFormat.0;
// create the workbook in the desired format with a single worksheet
ExcelWorkbook workbook = new ExcelWorkbook(workbookFormat);
workbook.EnableFormulaCalculations();
workbook.LicenseKey = _expertxlsLK;
// get the first worksheet in the workbook
ExcelWorksheet worksheet = workbook.Worksheets[0];
// set the default worksheet name
worksheet.Name = "ClaimInformation";
// load data from DataTable into the worksheet
worksheet.LoadDataTable(sampleDataTable, 1, 1, true);
worksheet.Workbook.EnableFormulaCalculations();
workbook.Save(#"M:\Rupesh\test.xlsx");
workbook.Close();
}
This is a niche problem so I will try to define everything to the best of my ability. I am using Excel 2007.
Our company uses excel to produce our forms. We have many workers who use these forms. We do not want our spreadsheets to contain macros for security reasons, but we still need to use VBA to perform mass operations on data in the normal workbook. As a result, all of our macros are defined in each employee's PERSONAL.xlsb file and can be called on our normal workbook. Since we run many different macros over this workbook, it is really handy to have shortcuts to call them. The shortcuts are defined in excel as seen here:
The PERSONAL.xlsb file is special because Excel will automatically open this as a hidden background workbook whenever you open any excel file. This is great because it enables you to call user-defined macros in PERSONAL.xlsb on the current workbook, without needing the current workbook to be macro enabled.
The .xlsb is a binary extension and uses some proprietary Microsoft compression algorithm. The issue is that writing macros and VBA code is done through the VBA IDE bundled in Excel. This means that the code that you write isn't stored in plaintext, and excel is acting as a middleman that reads/writes your VBA code to a binary blob in the .xlsb file.
Since we use (and plan on adding) many macros, It would be highly advantageous to code them as plain files in an editor of my choice and use git to keep track of changes. Ideally, I want a development folder with a bunch of different .vba files to logically separate each macro. I then want a plain text configuration file that defines optional shortcut keys to each one of the .vba code modules.
Then, when I am happy with changes, I want to run a program that uses the Microsoft Excel Interop to compile this all into a nice PERSONAL.xlsb file that can be easily kept up to date and sent to other employees. I have nearly all of this implemented, but I can't figure out how to assign shortcut keys to a code module.
Here is my example code that compiles VBA files to a .xlsb file:
using Microsoft.Office.Interop.Excel;
using Microsoft.Vbe.Interop;
using System;
using System.IO;
namespace BinaryCompile
{
class Program
{
private static string path = #"C:\Users\Path\To\Source";
static void Main(string[] args)
{
var excel = new Microsoft.Office.Interop.Excel.Application();
//Console.WriteLine(path);
var workbook = excel.Workbooks.Add();
var project = workbook.VBProject;
include_files(get_vba_files(), ref project);
excel.MacroOptions();
workbook.SaveAs(path + "/PERSONAL.xlsb", XlFileFormat.xlExcel12);
workbook.Close();
Console.Read();
excel.Quit();
}
static string[] get_vba_files()
{
return Directory.GetFiles(path, "*.vba");
}
static void include_files(string[] vba_files, ref VBProject project)
{
foreach (string source in vba_files)
{
var module = project.VBComponents.Add(vbext_ComponentType.vbext_ct_StdModule);
module.CodeModule.AddFromFile(source);
module.Name = Path.GetFileNameWithoutExtension(source);
}
}
}
}
I can't find any documentation on how to assign shortcut keys to these programatically generated modules.
This is one option, if you're free to modify the vba file. If you create an macro in Excel, assign a shortcut, and then export the module, you will see the file has the following structure:
Attribute VB_Name = "MyModule"
Sub MyFunction()
Attribute MyFunction.VB_ProcData.VB_Invoke_Func = "y\n14"
'Do Your stuff
End Sub
Sub MyFunction2()
Attribute MyFunction2.VB_ProcData.VB_Invoke_Func = "q\n14"
'Do more stuff
End Sub
The first character in "y\n14" and "q\n14" will be your shortcut key to be used with Ctrl key, in these cases, Ctrl+y and Ctrl+q.
Side note: I tried your code, and I only could make it work by removing the excel.MacroOptions(); line.
Using C# to write a method that takes a single worksheet out of a workbook and saves it as HTML.
I am using the Worksheet.SaveAs method as described on MSDN.
However, when I look at the output it has gone and saved all of the worksheets within the workbook, not just the one I selected. It's as though Worksheet.SaveAs and Workbook.SaveAs just do the same thing.
Simplified code:
public static void saveSingleSheetAsHTML(string workbook, string destination, string sheetName)
{
Application excel = new Application();
excel.Workbooks.Open(Filename: workbook);
Microsoft.Office.Interop.Excel._Worksheet worksheet = excel.Worksheets[sheetName];
var format = Microsoft.Office.Interop.Excel.XlFileFormat.xlHtml;
worksheet.SaveAs(destination, format);
}
Now when I open the resulting HTML file it has only gone and exported the entire workbook, not the sheet.
As said by Tim Williams in a comment I found after hitting a link posted by I love my monkey above:
"You cannot call SaveAs on a worksheet - first call .Copy to create a
standalone new workbook containing only that sheet, then save that
workbook."
No idea why you cannot. The docs on MSDN do not give any clue about this and suggest it should be possible.
So having created a new workbook:
var newbook = excel.Workbooks.Add(1);
Copy the sheet over, which will place it as the first sheet:
excelWorksheet.Copy(newbook.Sheets[1]);
Then delete the default "Sheet1", which will always be the 2nd sheet:
newbook.Worksheets[2].Delete();
Then call the SaveAs method and then close the new book:
newbook.SaveAs(Filename: destination, FileFormat: format);
newbook.Close();
This did save the new workbook as HTML, but also put the tabs at the bottom, which I was hoping to avoid as there is only 1 tab now. It does meet my minimum needs, though I would like to figure out how to make it a bit neater.
When I run this code it opens file in Readonly mode but I want to open my document file in Editable mode.I have already readonly mode set to false.This is the code which i have using:-
Microsoft.Office.Interop.Word.Application winword = new Microsoft.Office.Interop.Word.Application();
Microsoft.Office.Interop.Word.Document document = new Microsoft.Office.Interop.Word.Document();
try
{
//Set status for word application is to be visible or not.
//Create a missing variable for missing value
object readOnly = false;
object missing = System.Reflection.Missing.Value;
object isVisible = true;
document = winword.Documents.Open(pathToFile, ReadOnly: false, Visible: true);
document.Activate();
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(winword);
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(document);
}
catch (Exception ex)
{
// WB.Close(false, Type.Missing, Type.Missing);
throw;
}
My guess is that you can't do it. Readonly mode is provided in part as a security measure to stop some macros from executing in Word. Thus, to provide an SDK overriding it would be a risk to end-users. You might be able to get around it by running the exe directly with a parameter of the filename, since then it would be like a person double-clicking the icon, but I'm not familiar with what libraries are or are not available in WPF. In good ol'-fashioned consoles or Windows Forms, you'd be looking at
System.Diagnostics.Process.Start([the path of Word.exe], pathToFile);
but you'd have to be careful about finding the path to Word.exe, since that could vary based on the version of word and what installation instructions were given. It's conceivable that those COM objects will expose the path somehow, since there's a good chance they'd need to know it, but yet again I'm not familiar with them.
I am trying to get the name of the workbook before it actually opens up.
((Excel.AppEvents_Event)this.Application).WorkbookOpen += new Excel.AppEvents_WorkbookOpenEventHandler(App_WorkBookOpen);
private void App_WorkBookOpen(Excel.Workbook Wb)
{
System.Windows.Forms.MessageBox.Show("Shakti " + " " + Wb.Name);
}
With the handler as shown above, Excel application shows the workbook name when it is opened completely.My intention is to do some formal check before it is actually opened up and data is shown to the user.
Is there any way or mechanism to extract the file name before the contents are loaded on to Excel and shown to the user? Any sort of help is highly appreciated.Thanks.
AFAIK you can't do that. But like I mentioned in my comment you could hide the workbook the moment it is visible. So the user will see the workbook open for a split second and then go invisible. In that split second you can read the name of the workbook and then hide the workbook.
Based on your calculations/conclusion you can then close/unhide the workbook as required.
You can hide the workbook using
Wb.Windows[1].Visible = false;
No you can't.
You anyway could create a Macro on a WorkBook Module with Open class tag as here:
Private Sub Workbook_Open()
Dim ws As Workbooks
For Each ws In ActiveWorkbook.Worksheets
MsgBox ws.Name
Next
ActiveWorkbook.Worksheets.Close
End Sub
Then call this sub via c# on opening the file, this sub runs before loading the workbook then it closes it. It has not that sense, because you'll never access the wb again...
Maybe with some tweaking here and there you could accomplish your task, but it depends to you.
Hope it helps...
Isn't Wb.name the same as the filename? In which case, since you must know the filename/location in order to open it, you can check it beforehand?