I am working on a web App where user can upload an Excel file and I need to copy data from the user worksheet to a destination worksheet in order to do some calculation. To do so, I have the following code:
public class ExcelCtrl
{
private Excel.Application excelApp = null;
private Excel.Workbook srcworkbook = null;
private Excel.Workbook destworkbook = null;
public void excel_init(String srcpath, String destpath, string copyrange)
{
//Open Excel
this.excelApp = new Excel.Application();
//Open user's file
this.srcworkbook = excelApp.Workbooks.Open(srcpath);
Excel.Worksheet srcworksheet = (Excel.Worksheet)srcworkbook.Worksheets.get_Item(1);
//Open calculation file
this.destworkbook = excelApp.Workbooks.Open(destpath);
Excel.Worksheet destworksheet = (Excel.Worksheet)destworkbook.Worksheets.get_Item(1);
//Range of copy
Excel.Range from = srcworksheet.get_Range(copyrange);
Excel.Range to = destworksheet.get_Range(copyrange);
//Copy
from.Copy(to);
//Close user's file
srcworkbook.Close();
//Open Xla file
excelApp.Workbooks.Open("someXlaFile.xla");
excelApp.Workbooks.Open("AnotherXlaFile.xla");
}
Basically I have to different method to run different calculations and they have the following structure. What differ one calculation method to another are just the macro called, the number of macro and the copy range.
public static string Calculation1(String InputFileName, String CurDir)
{
//The Excel calculation file and its path
string filename = "CalculationFile.xls";
string path_server = ExcelCtrl.DossierCalcs + filename;
ExcelCtrl excel = new ExcelCtrl();
excel.excel_init(CurDir + "\\" + InputFileName, ExcelCtrl.DossierCalcs + filename, "A1:Z105");
//excel.excel_run("Macro1");
//The rest is not important
path_server = CurDir + "\\Resultats - " + InputFileName;
excel.excel_run("AnotherMacro", path_server);
excel.excel_close();
return path_server;
}
Now all work fine, except one calculation (the one above). I am unable to copy data from the user worksheet.
I have tested to :
(normal usage) upload an Excel file with some new data and when I download the file after calculation, it is still the old data.
reduce the range of copy ( I though maybe it is too big) to "A1:Z50" then "A1:A2". However, I have another calculation file where I copy a range of "A1:M730" and it works fine.
copy it manually with Ctrl + C; Ctrl + V (I thought maybe the worksheet is protected from modification or something)
With the first 2 tests, I still got old data (not the user data) and the last one works, I can paste user data; though not very useful if someone need to do it manually everytime an user ask for this calculation.
I hope this is enough for you to understand my problem and hope you can guide me.
Thanks
EDIT
Hello,
Just to clarify a little bit about what I am doing. I have an web app where user can download an Excel xlsx file and they have to fill in with their data. After that, They have to upload their file to the server and choose the calculation they want to run. On the server side, I copy their data (see code above) to the corresponding Excel calculation file. So for each calculation I have one input file for the user and one calculation file to run. In total I have 14 input files and 14 calculations files and 13 of them work fine.
I have done some more tests, the following tests do not copy my data :
(And I am using Excel 2010)
Changing the name of my destination Excel file to something more common because there were a "#" in the file name.
Changing the name of my destination Excel file to one another destination file where the copy works.
Changing the worksheet color (I really don't believe that will solve my problem but I have nothing to lose)
Deleting worksheets from my destination file one by one
And the following tests work (data are copied to the destination file) :
Copying to a new Excel file
Copying to an other Excel calculation file (let's say file B) where I know the copy works
My thought for the last case is because when I open my problematic Excel file, 2 warnings come up. The first one says that the workbook contains link to other data sources and ask me if I want to update it (even after updating, it keeps asking me everytime I open it) and the second one says that the workbook contains links that can not be updated.I have also this 2 warnings when I open file B but with this file the copy works.
So I have tried to delete all links in the file and it does not work either. Futhermore, those links are used in my 13 others files.
I am kind of lost now since I have deleted all worksheet and links from my Excel file and it still won't copy. The only difference I see between my problematic file and a new file is that the former contain Macro.
Related
We get an excel file in a specific location where the name of the file may vary every time.
So every time we rename the excel file manually to "Report.xlsx" and then we have some operation to be done using a script task. The file_Path + file_Name is hardcoded in the script task as
Microsoft.Office.Interop.Excel.Workbook workBook = excelApp.Workbooks.Open(#"D:\Desktop\Report.xlsx");
Is there a way to get the file name from the file location and pass it to the above code ?
Note:
The file Path is static but the file name will vary every time.
At a time there will be only one excel file in the file Path.
We are already using a Sequence Container so cant change it.
Thanks in advance..
This will let you use the actual file name. Make sure to reference System.Linq
var dir = new System.IO.DirectoryInfo(#"D:\Desktop");
var fullFilePath = dir.GetFiles("*.xlsx").Select(f => f.FullName).First();
if(fullFilePath != null)
Microsoft.Office.Interop.Excel.Workbook workBook = excelApp.Workbooks.Open(fullFilePath);
I have an excel file in my project which is listed as resource.
Now I try to open it with a button click like this:
private void Button_Click_Blist(object sender, RoutedEventArgs e)
{
Excel.Application xl = new Excel.Application();
Excel.Workbook wb = xl.Workbooks.Open("Blist.xlsx");
}
My problem is that it says that it can't find the file and throws this exception:
System.Runtime.InteropServices.COMException
We couldn't find 'Blist.xlsx'. Was the object perhaps moved, renamed,
or deleted?
This code uses OLE Automation to start Excel and tell it to open a file in the relative path Blist.xlsx. The executable in this case is Excel, not your own application. The relative path will be resolved using Excel's working directory.
To avoid this problem, pass the absolute file path to Excel :
var fullPath=Path.GetFullPath("Blist.xlsx");
Excel.Workbook wb = xl.Workbooks.Open(fullPath);
Another possibility, which gives no control of (or dependency on) Excel, is to just "start" the file with Process.Start, eg :
Process.Start("Blist.xlsx");
Or
var fullPath=Path.GetFullPath("Blist.xlsx");
Process.Start(fullPath);
The Windows Shell will find the application that can open this document based on its extension and start it, passing the file path as an argument. This can start Excel, Libre Calc or any other application registered to open this particular file extension.
So I tried this and apparently the .Open() method some extra complexety with relative paths (see #PanagiotisKanavos comment). You can make a work around, by getting the current directory path, and pre-pending it, giving the absolute path of the file:
string filename = "Blist.xlsx";
string currentPath = Directory.GetCurrentDirectory();
var xl = new Microsoft.Office.Interop.Excel.Application();
var wb = xl.Workbooks.Open(currentPath + "\\" + filename);
xl.Visible = true;
However, you should (almost) never use hardcoded file names in your code. So the above solution is just an example, not something to copy into production code...
I have created an Excel Add-in using VSTO in C#. I want to create a new Excel file from a template located on a SharePoint site. A file picker dialog box is used so the user can chose which file to use as a template. Everything works fine exept the new workbook is created as read only. If I copy the template file on my computer, and use the same program to pick that file as a template, the new workbook is not created as read only.
The file on the sharePoint is not being open elseware when creathing the new file. Is there a way to specify the sharePoint library is a safe source? Or to set the newly created workbook readonly property to false?
{
string pathSP= #”\\Business.sharepoint.com#SSL\teams\group\NDC\”;
if (System.IO.Directory.Exists(pathSP))
{
Excel.Application excelObj = Globals.ThisAddIn.Application;
Office.FileDialog fileDialog = excelObj.FileDialog[Office.MsoFileDialogType.msoFileDialogFilePicker];
fileDialog.InitialFileName = initialPath;
fileDialog.AllowMultiSelect = false;
fileDialog.InitialView = Office.MsoFileDialogView.msoFileDialogViewDetails;
fileDialog.Title = "Create Excel file from template";
fileDialog.Filters.Clear();
fileDialog.Filters.Add("Excel template", "*.xls; *.xlsx; *.xlsm; *.xltx; *.xltm; *.xlt", 1);
string TemplatePath;
if (fileDialog.Show() == -1)
{
templatePath = fileDialog.SelectedItems.Item(1);
fileDialog = null;
}
else
{
templatePath=""
fileDialog = null;
}
if (templatePath != "")
{
Excel.Workbook ws= excelObj.Workbooks.Add(templatePath);
}
}
else
{
MessageBox.Show("SharePoint site is not available", "Create Excel file from template", MessageBoxButtons.OK,MessageBoxIcon.Exclamation);
}
}
for the two ways you mentioned:
set the share point library as a safe source - this can be achieved by setting the excel setting: Options -> Trust Centre -> Trust Centre Settings -> Trusted Locations -> add the sharepont location
set the file access (readonly=false) at the end of your process
Actually as a general practice when dealing with template file (not limited to excel), the system should copy the template file to a local temp location (ideally the running user's TEMP folder), use it and then delete it afterwards. this way would avoid all kinds of problems such as file-lock-by-other-user/process problems.
So I think your problem is the Workbooks.Add(). Check out what Microsoft says about it:
[Workbooks.Add()] Determines how the new workbook is created. If this argument is a string specifying the name of an existing Microsoft Excel file, the new workbook is created with the specified file as a template.
I believe the workbook you're creating is a carbon copy of whatever the sharepoint server has, including permissions. The fact it works locally is another clue that sharepoint might be fiddling with permissions.
I suggest try saving a copy of the file locally. You can even use the SaveFileDialog object to give the user a GUI to save their new copy.
SaveFileDialog userSaveFileDialog = new SaveFileDialog();
userSaveFileDialog.Filter = "Excel 2007 and later | *.xlsx, Excel Macro Enabled Worksheet | *.xlsm, I'm guessing this is a 2007 template | *.xltx, Template Macro maybe | *.xltm, I almost definitely think this is a template file | *.xlt";
userSaveFileDialog.Title = "Save an Excel File";
userSaveFileDialog.ShowDialog();
this.Application.ActiveWorkbook.SaveCopyAs(#userSaveFileDialog.FileName);
Once you're done, you can programmatically open the newly saved workbook using userSaveFileDialog.FileName as your filepath.
I have a folder with over 2000+ MS Excel 2010 .XLSX spreadsheets and I need to perform the following actions:
I need to open each individual file
Copy the content of cell B4 (+ each file has unique content on cell B4), and
append the content of cell B4 to the original file name
How can I fix this error so I can successfully rename my spreadsheets as mentioned above?
//file rename code
DirectoryInfo d = new DirectoryInfo(#"C:\Torename\");
FileInfo[] infos = d.GetFiles();
foreach (FileInfo f in infos)
{
Microsoft.Office.Interop.Excel.Application excel = new Microsoft.Office.Interop.Excel.Application();
Workbook wb = excel.Workbooks.Open(f.FullName);
Worksheet excelSheet = wb.ActiveSheet;
//Read the first cell
string test = excelSheet.Cells[4, 2].Value.ToString();
File.Move(f.Name, new_filename);
***Thank you for your assistance that did the trick
File.Move(f.FullName, new_filename);
You have to use FullName, you need the full path.
Edit: Not part of your Question, but:
I'm not sure how Workbooks.Open works, but if you run into errors you might close the file before renaming it.
Also Adams comment.
Close the workbook before moving it. Make sure to release all the resources associated with that file.
And make sure you use the whole path in the names
I have application, which do something. Generaly the main their task is to analise and drawing charts after getting data from excel file. This application can do at the same time max. 10 analise and each of them are execute in a separate thread in a separate tabPage control. Everything is great to the moment when is appearing 3 problems.
I can't reading data from one excel file do a few analises. If I'm using one file to one analise and I want to use this same file to another it's not possible beacuse there is some massage that this file is acctually using by another process. To read data from excel file i'm using oleDBConnection schema. How to solve this problem.
I have this same problem to write data to one file. How to force my application to write same message from different threads to one file.
If I want to close my application (when one of analise is working) there is show me some message with communication: "Interruption lasted thread (or something like that)". I don't know why. I support this
Please help me to solve this problems beacuse I'm trying to solve it sice monday and there is no effect :(
Possible Example
string FullExcelFilePath = "C:\ExcelFile.xls";
Excel.Application xlApp = new Excel.Application()
Excel.WorkBook xlWorkBook1 = xlApp.WorkBooks.Add(FullExcelFilePath);
Excel.WorkBook xlWorkBook2 = xlApp.WorkBooks.Add(FullExcelFilePath);
//then in your first ThreadCall
foreach(Excel.WorkSheet in xlWorkBook1.Sheets)
{
//get what you want
}
//then in your 2nd ThreadCal
foreach(Excel.WorkSheet in xlWorkBook2.Sheets)
{
//get what you want
}
OTHER Option you could do is:
You Could make a copy of the Xls for the other thread, and then
use a copy of the xls file in the Other Thread.
File.Copy(strFileName, strDestination);
then Afterwards Delete it
File.Delete(strFileNameSecondVersion)