when i tried to save a read- only ppt/pptx to a pdf i got a msg as shown below
below is my code:
Microsoft.Office.Interop.PowerPoint.Application pptApplication = new Microsoft.Office.Interop.PowerPoint.Application();
pptApplication.DisplayAlerts = PpAlertLevel.ppAlertsNone;
Microsoft.Office.Interop.PowerPoint.Presentation pptPresentation = pptApplication.Presentations.Open("E:\\Share Box\\data.pptx", MsoTriState.msoTriStateMixed,
MsoTriState.msoFalse, MsoTriState.msoFalse);
string temp = pptPresentation.ReadOnly.ToString();
pptPresentation.SaveAs("E:\\Share Box\\"+DateTime.Now.Second.ToString(), PpSaveAsFileType.ppSaveAsPDF, MsoTriState.msoTrue);
pptPresentation.Close();
Marshal.FinalReleaseComObject(pptPresentation);
pptPresentation = null;
pptApplication.Quit();
Marshal.FinalReleaseComObject(pptApplication);
pptApplication = null;
GC.Collect();
anyone could help me to fix this.
I tried this code and it's working fine.For this I used interop assemblies downloaded from
http://www.microsoft.com/en-in/download/details.aspx?id=3508
Please see this also
http://support.microsoft.com/kb/873433
Related
I'm working on a C# project that create, encrypt and send an excel file as an e-mail attachment.
I'm not looking to protect the excel, but encrypt it and set a password for opening it.
Is it even possible with the OpenXML SDK ?
I tried that, but I don't think this is for encrypting :
string hexConvertedPassword = HexPasswordConversion("Azerty123");
WorkbookProtection WorkbookProt = new WorkbookProtection()
{
WorkbookPassword = hexConvertedPassword,
RevisionsPassword = hexConvertedPassword,
LockRevision = true,
LockStructure = true,
LockWindows = true,
};
Workbook workbook = new Workbook();
workbook.Append(WorkbookProt);
I have already search in the documentation, but may have missed it.
I know some library can do it like devexpress, EasyXLS, Spire.Xls, etc, but those are very expensive.
You can try to encrypt the content of DOCUMENT via reading cell by cell and generate a new .xlsx file.
WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart;
WorksheetPart worksheetPart = workbookPart.WorksheetParts.First();
SheetData sheetData = worksheetPart.Worksheet.Elements<SheetData>().First();
string text;
foreach (Row r in sheetData.Elements<Row>())
{
foreach (Cell c in r.Elements<Cell>())
{
// send to ecryption function.
text = c.CellValue.Text;
Console.Write(text + " ");
}
}
For more details visit: https://learn.microsoft.com/en-us/office/open-xml/how-to-parse-and-read-a-large-spreadsheet
In the end I used FreeSpire.XLS to load my existing Excel file and add the encryption over it. Hopefully there is no limitation to load and save file with the free version.
I read an excel file (.xlsm; password-protected) with a vb.net application. I use the following interfaces:
System.IO.filestream
Syncfusion.XlsIO (NuGet)
That works, but I want to open it in ReadOnly-Mode, so that any other people can use this file with MS Office (write, save, ...).
Code:
Imports Syncfusion.XlsIO
Private SyncEE As Syncfusion.XlsIO.ExcelEngine
Private SyncWB As Syncfusion.XlsIO.IWorkbook
Private SyncFS As System.IO.FileStream
Public Sub new
SyncEE = New ExcelEngine
SyncFS = New FileStream(PathFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
SyncEE.Excel.DefaultVersion = ExcelVersion.Excel2016
SyncWB = SyncEE.Excel.Workbooks.Open(SyncFS, ExcelParseOptions.Default, openReadOnly, password)
SyncWB.Unprotect(password)
SyncWB = SyncEE.Excel.Workbooks.Open(SyncFS, ExcelOpenType.Automatic)
' read....
'discard
SyncWB.Close()
SyncWB = Nothing
SyncEE.Dispose()
SyncEE = Nothing
SyncFS.Dispose()
SyncFS = Nothing
End Sub
I tried it step by step and found out that i block the file at row:
SyncFS = New FileStream(PathFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
and I release the file at the 'discard' rows.
Blocking means that no one can edit and save the excel-file manually in MS Excel while I read it.
Greetings from Syncfusion.
You are blocking the file on loading the file using FileStream, as mentioned by you and you are discarding the FileStream object only at the end of your entire program. You can discard the FileStream object immediately after loading it into a workbook object so that others can use the file with MS Office (write, save, …) while you are reading it. Hence, we have modified your code as below to achieve your requirement.
Code snippet:
Private Sub new
SyncEE = New ExcelEngine
SyncFS = New FileStream(PathFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
SyncEE.Excel.DefaultVersion = ExcelVersion.Excel2016
SyncWB = SyncEE.Excel.Workbooks.Open(SyncFS, ExcelParseOptions.Default, openReadOnly, password)
'Discard FileStream
SyncFS.Dispose()
SyncFS = Nothing
' read....
'discard
SyncWB.Close()
SyncWB = Nothing
SyncEE.Dispose()
SyncEE = Nothing
End Sub
Note: I work for Syncfusion.
Regards,
Shamini
I tried with Aspose cell.
But I am able to add pdf file properly.
When I add jpg file, it shows in the excel file but doesnot get opened.
I tried with following way.
sheet.getOleObjects().get(oleObjectIndex).setImageData(binary);
sheet.getOleObjects().get(oleObjectIndex).setLeftCM(oleObjectIndex);
sheet.getOleObjects().get(oleObjectIndex).setDisplayAsIcon(true);
Here image shown like a thumbnail , but I dont want that.
sheet.getOleObjects().get(oleObjectIndex).setObjectData(binary);
//sheet.getOleObjects().get(oleObjectIndex).setFileType(oleFileType);
sheet.getOleObjects().get(oleObjectIndex).setDisplayAsIcon(true);
sheet.getOleObjects().get(oleObjectIndex).setLeftCM(oleObjectIndex);
Here it shows proper icon for the file but file does not get opened when double clicked.
Help from the community is highly apraciated.
Thank you.
See the following two lines of code that you also need to add:
sheet.getOleObjects().get(oleObjectIndex).setFileFormatType(FileFormatType.UNKNOWN);
sheet.getOleObjects().get(oleObjectIndex).setObjectSourceFullName(path);
Here is complete sample code that I tested and it works fine:
e.g
Sample code:
// Get the image file.
String path = "e:\\test\\myfile.jpg";
File file = new File(path);
// Get the picture into the streams.
byte[] img = new byte[(int) file.length()];
FileInputStream fis = new FileInputStream(file);
fis.read(img);
// Instantiate a new Workbook.
Workbook wb = new Workbook();
// Get the first worksheet.
Worksheet sheet = wb.getWorksheets().get(0);
// Add an Ole object into the worksheet with the image shown in MS Excel.
int oleObjIndex = sheet.getOleObjects().add(14, 3, 200, 220, img);
OleObject oleObj = sheet.getOleObjects().get(oleObjIndex);
// Set embedded ole object data and other attributes.
oleObj.setObjectData(img);
oleObj.setDisplayAsIcon(true);
oleObj.setFileFormatType(com.aspose.cells.FileFormatType.UNKNOWN);
oleObj.setObjectSourceFullName(path);
// Save the excel file
wb.save("f:\\files\\tstoleobject1.xlsx");
Hope, this helps a bit.
PS. I am working as Support developer/ Evangelist at Aspose.
i just use the same code,but i found when i open the new Excel,it shows as a image,i have to check it twice to transfer it to an OLE.
whats worry
I have an Excel document that is created using Excel Interop written in VB.net. Adapting information from this post, I am able to successfully create a workbook and write its CustomDocumentProperties using:
Dim objNewApp As Excel.Application
Dim objNewBook As Excel._Workbook
Dim objNewBooks As Excel.Workbooks
objNewApp = New Excel.Application With {
.DisplayAlerts = True,
.Visible = True,
.UserControl = True,
.ScreenUpdating = True
}
objNewBooks = objNewApp.Workbooks
objNewBook = objNewBooks.Add
Dim properties As Object = objNewBook.CustomDocumentProperties
Dim propertiesType As Type = properties.[GetType]()
Dim documentClient As Object() = {"Client", False, Core.MsoDocProperties.msoPropertyTypeString, "In-Progress"}
propertiesType.InvokeMember("Add", BindingFlags.InvokeMethod, Nothing, properties, documentClient)
However, I have not been able to successfully read this property after it is set. After doing a thorough search, most posts on the topic here on SO, as well as MSDN, suggest reading this missing MSDN article to learn more about how to do this, noting how goofy it is to do in Interop in general. However, I am using Interop for the rest of my program, so I would like to find an Interop-specific solution (instead of VSTO).
Adapting from this post, I believe my current code is on the right track:
Dim ReadClient As String = "Client"
Dim ObjReadClient = propertiesType.InvokeMember("Item", BindingFlags.GetProperty, Nothing, properties, New Object() {ReadClient})
Dim TypeReadClient As Type = ObjReadClient.GetType
Dim ClientString As String
ClientString = TypeReadClient.InvokeMember("Value", BindingFlags.GetProperty, Nothing, properties, New Object() {})
However, when I run this I receive an System.Runtime.InteropServices.COMException:
"Unknown name. (Exception from HRESULT: 0x80020006 (DISP_E_UNKNOWNNAME))"
Doing more research, this appears to be due to the "Value" piece on the last line of code. I was unable to figure out where to go from there.
Does anyone have any idea as to this last piece of the puzzle? I'd be happy to clarify anything if needed!
Here is the solution for my particular problem:
Dim ReadClientIndex As String = "Client"
Dim ReadClientValue As String
Dim ObjReadClient As Object = propertiesType.InvokeMember("Item", BindingFlags.GetProperty, Nothing, properties, New Object() {ReadClientIndex})
Dim TypeReadClient As Type = ObjReadClient.GetType()
ReadClientValue = TypeReadClient.InvokeMember("Value", BindingFlags.GetProperty, Nothing, ObjReadClient, New Object() {})
Apart from cleaning up the code, the issue was that I should have referred to "ObjReadClient" as the argument in the last line - not the "properties" variable set earlier.
However, since there is a notable lack of documentation on this topic in VB.net or C#, here are some resources that might help future users:
Link 1: Provided code originally in the missing MSKB article (in C#, copied again below for preservation.):
Word.Application oWord;
Word._Document oDoc;
object oMissing = Missing.Value;
object oDocBuiltInProps;
object oDocCustomProps;
//Create an instance of Microsoft Word and make it visible.
oWord = new Word.Application();
oWord.Visible = true;
//Create a new Document and get the BuiltInDocumentProperties collection.
oDoc = oWord.Documents.Add(ref oMissing, ref oMissing, ref oMissing,
ref oMissing);
oDocBuiltInProps = oDoc.BuiltInDocumentProperties;
Type typeDocBuiltInProps = oDocBuiltInProps.GetType();
//Get the Author property and display it.
string strIndex = "Author";
string strValue;
object oDocAuthorProp = typeDocBuiltInProps.InvokeMember("Item",
BindingFlags.Default |
BindingFlags.GetProperty,
null,oDocBuiltInProps,
new object[] {strIndex} );
Type typeDocAuthorProp = oDocAuthorProp.GetType();
strValue = typeDocAuthorProp.InvokeMember("Value",
BindingFlags.Default |
BindingFlags.GetProperty,
null,oDocAuthorProp,
new object[] {} ).ToString();
MessageBox.Show( "The Author is: " + strValue,"Author" );
//Set the Subject property.
strIndex = "Subject";
strValue = "The Subject";
typeDocAuthorProp.InvokeMember("Item",
BindingFlags.Default |
BindingFlags.SetProperty,
null,oDocBuiltInProps,
new object[] {strIndex,strValue} );
//Add a property/value pair to the CustomDocumentProperties collection.
oDocCustomProps = oDoc.CustomDocumentProperties;
Type typeDocCustomProps = oDocCustomProps.GetType();
strIndex = "Knowledge Base Article";
strValue = "Q303296";
object[] oArgs = {strIndex,false,
MsoDocProperties.msoPropertyTypeString,
strValue};
typeDocCustomProps.InvokeMember("Add",BindingFlags.Default |
BindingFlags.InvokeMethod, null,
oDocCustomProps, oArgs );
MessageBox.Show("Select \"Properties\" from the File menu "
+ "to view the changes.\nSelect the Summary tab to view "
+ "the Subject property and the Custom tab to view the Knowledge"
+ "Base Article property.", "Check File Properties",
MessageBoxButtons.OK,MessageBoxIcon.Information);
Link 2: Notes that it is easier to accomplish in VB.net, but that C# will soon support late-binding using "Dynamic" (written 10 years ago). I found another post somewhere that explained the importance of "Dynamic" as an answer in C#, but was unable to find it again to link to.
Link 3: This information is specific to Excel, but I believe it may help someone looking for it specifically.
Link 4: This gives an example mistaking VTSO and Interop, which may help users differentiate between the two.
To get custom properties using c# is bit a different approach. Pls check these 2.
Not copying whole code for dedup.
How can I read excel custom document property using c# excel interop
How to get CustomDocumentProperties using Excel Interop?
I am developing a website on VisualStudio using VB. In one section of my site I make a DataBase Query, store the result in a DataTable and display it. I give the user the option of dowloading the information, what I would like to do is to download an XLS file to the client's side with the information in the datatable without creating the xls on the server side.
I currently have the following code section to send the file to the user
Dim fileToDownload = Server.MapPath("~/docs/QuejometroVF.pdf")
Response.ContentType = "application/octet-stream"
Dim cd = New ContentDisposition()
cd.Inline = False
cd.FileName = Path.GetFileName(fileToDownload)
Response.AppendHeader("Content-Disposition", cd.ToString())
Dim fileData = System.IO.File.ReadAllBytes(fileToDownload)
Response.OutputStream.Write(fileData, 0, fileData.Length)
But it requires a path to a local file in order to send it.
First I would like to know how to create a xls file from the datatable (only in memory) and then send that object as a file to the client's computer. If it is not possible, Could you tell me how to write the xls file in my server so I can then send it using the code above? I have not really figured out how to do it yet.
I was thinking on doint it that way because I don't want to keep files in the server when I already have that information on the database and I don't pretend on keeping that file stored.
Thank you
I export data to xls file using the following code, my backend is an Oracle database and that's where I get the data:
Dim MyConnection As OracleConnection = OpenConnection(Session("USERNAME"), Session("PASSWORD"))
Dim MyDataSet As New DataSet
MyDataSet = GetExportData(MyConnection, Session("UserDataKey"), Session("CompoundKey"), Session("LastOfCompoundKey"))
'I rename the dataset's table columns to what I want in the xls file
MyDataSet.Tables!data.Columns(0).ColumnName = "IDNumber"
MyDataSet.Tables!data.Columns(1).ColumnName = "FirstName"
MyDataSet.Tables!data.Columns(2).ColumnName = "LastName"
MyDataSet.Tables!data.Columns(3).ColumnName = "Address"
MyDataSet.Tables!data.Columns(4).ColumnName = "City"
MyDataSet.Tables!data.Columns(5).ColumnName = "State"
MyDataSet.Tables!data.Columns(6).ColumnName = "ZipCode"
MyDataSet.Tables!data.Columns(7).ColumnName = "Phone_Area"
MyDataSet.Tables!data.Columns(8).ColumnName = "Phone_Prefix"
MyDataSet.Tables!data.Columns(9).ColumnName = "Phone_Suffix"
MyDataSet.Tables!data.Columns(10).ColumnName = "Email"
MyDataSet.Tables!data.Columns(11).ColumnName = "BirthDay"
Response.ClearContent()
'I create the filename I want the data to be saved to and set up the response
Response.AddHeader("content-disposition", "attachment; filename=" & Replace(Session("Key0"), " ", "-") & "-" & Session("Key1") & "-" & Replace(Replace(Trim(Session("Key2")), ".", ""), " ", "-") & ".xls")
Response.ContentType = "application/excel"
Response.Charset = ""
EnableViewState = False
Dim tw As New System.IO.StringWriter
Dim hw As New System.Web.UI.HtmlTextWriter(tw)
'Create and bind table to a datagrid
Dim dgTableForExport As New DataGrid
If MyDataSet.Tables.Count > 0 Then
If MyDataSet.Tables(0).Rows.Count > 0 Then
dgTableForExport.DataSource = MyDataSet.Tables(0) ' .DefaultView
dgTableForExport.DataBind()
'Finish building response
Dim strStyle As String = "<style>.text { mso-number-format:\#; } </style>"
For intTemp As Integer = 0 To MyDataSet.Tables(0).Rows.Count - 1
For intTemp2 As Integer = 0 To MyDataSet.Tables(0).Columns.Count - 1
dgTableForExport.Items(intTemp).Cells(intTemp2).Attributes.Add("class", "text")
Next
Next
End If
End If
dgTableForExport.RenderControl(hw)
Response.Write(style)
' Write the HTML back to the browser.
Response.Write(tw.ToString())
Response.End()
'Close, clear and dispose
MyConnection.Close()
MyConnection.Dispose()
MyConnection = Nothing
I copied and pasted this from one of my projects, it's untested and may contain error but should get you started.
You can use a MemoryStream or to write the file to Response stream using Response.Write method.
Creating an excel file from a data table is fairly easy as you can just create a GridView and bind the table to it.
Here is a code snippet that does what you need.
Public Sub DownloadExcel(outputTable as System.Data.DataTable)
Dim gv As New GridView
Dim tw As New StringWriter
Dim hw As New HtmlTextWriter(tw)
Dim sheetName As String = "OutputFilenameHere"
gv.DataSource = outputTable
gv.DataBind()
gv.RenderControl(hw)
Response.AddHeader("content-disposition", "attachment; filename=" & sheetName & ".xls")
Response.ContentType = "application/octet-stream"
Response.Charset = ""
EnableViewState = False
Response.Write(tw.ToString)
Response.End()
End Sub
There are a few issues with this method:
This doesn't output a native excel file. Instead, it outputs the HTML for a GridView that Excel will detect and notify the user that the content doesn't match the extension. However, it WILL display in Excel correctly if the user selects 'Yes' from the dialog box.
Earlier versions of Firefox and Chrome didn't like this method and instead download the file with a .html extension. I just tested it in both browsers and it worked with the most up to date versions.
Ideally, you should probably use Excel on your webserver to create native spreadsheets, but this will work if you (like me) don't have the means to do so.