unable to loop through open Excel workbooks in C# - c#

I am currently consistently failing at a very simple task:
I want to loop through all currently open Excel-files (Workbooks)
Of course I did the usual googling for code snipes and found quite a bunch of ready-to-use code that should work according to the comments in the discussion threats and ratings. But for me they all just don’t work
I also saw people mentioning releasing COM Objects, but I didn’t really understand it and all the ready-to-go code examples don’t include it neither.
I am using:
Windows 10
Office 16
Visual Studio 2017 (V15.9.41)
COM-Reference 'Microsoft Excel 16.0 Object Library'
I modified the code snippets I found online, so my current code looks like this:
using System;
using Microsoft.Office.Interop.Excel;
private void PrintListOfOpenWB()
{
Microsoft.Office.Interop.Excel.Application xlApp;
xlApp = new Microsoft.Office.Interop.Excel.Application();
foreach (Workbook item in xlApp.Workbooks)
{
Console.WriteLine(item.Name);
}
}
I am using it as part of a WindowsFormsApp, so there is also using System.Windows.Forms etc, but I removed this part, so only the relevant code is shown here.
I do have multiple workbooks open and I do not get any error while compiling nor while running the code. But there is absolutely no output generated, because it directly jumps to the end of the foreach loop.
Any ideas what I am doing wrong?

I looked further into it and found the following solution that works for me.
using System;
using System.Runtime.InteropServices;
using Excel = Microsoft.Office.Interop.Excel;
private void PrintListOfOpenWorkbooks()
{
Excel.Application xlApp;
xlApp = (Excel.Application)Marshal.GetActiveObject("Excel.Application");
foreach(Excel.Workbook xlWorkBook in xlApp.Workbooks)
{
Console.WriteLine(xlWorkBook.Name);
}
}
Maybe this will help other people in the future as well.

This probably returns no output because the variable is empty, doing what you did you only created the variable that let you access the library method, and you can't populate that with an actual excel file, to do that do this:
Workbook workBook = xlApp.Workbooks.Open(yourExcelFilePath);
//Cycle through the workBook and display the sheets
workBook.Close(false, yourExcelFilePath, null);
Remember that the hierarchy of working with excel files (and this is practically the same with all the different libraries that helps you in doing this) is structured like this:
test = new Microsoft.Office.Interop.Excel.Application(); : This is used just to interface with the library methods
WorkBook : This is the actual equivalent of the full excel file you want to work on, and you need to populate it first
Worksheet: This is an entity that represent a single excel "page" inside the file
P.S: Re-reading the question I maybe have understood it wrong, can you specify if you want to show the name of excel files inside a folder or show the names of the single sheets inside a sigle excel file
To show the names of different excel files somewhere you can do this:
string[] temp = Directory.GetFiles(directoryPath);
List<string> ExcelFilesInDirectory = new();
foreach (var item in temp)
{
if (item.Contains(".xlsx"))
{
ExcelFilesInDirectory.Add(item);
}
}
Then with that list you can make the user select the file he wants to modify and then you can use the first code sample I sent to make it work

Related

File corrupted simply by opening and saving with no changes

Working on some code to update a spreadsheet but I noticed the isolated act of opening the spreadsheet and saving it corrupts it, resulting in the message
"We found a problem with some content in''. Do you want us to try to recover as much as we can?"
This can be replicated by the following code
FileInfo excelFile = new FileInfo("mysheet.xlsm");
using (ExcelPackage excel = new ExcelPackage(excelFile))
{
excel.Save();
}
The resulting file also shrinks from around 3MB to 2MB in the process.
Seems like this should be pretty straight forward but I must be missing something crucial.
I couldn't get to the bottom of the problem and switched to the Interop library.
DISCAIMER: This isn't an answer, but I want to post some code
I've tried to reproduce your problem, but with no luck. Steps as follows:
I've created a spreadsheet manually in Excel 2010. The text in cell A1 of Sheet1 simply reads "Hello". I've also added a code module in the macro editor (Alt-F11) with the following code:
Option Explicit
Sub Foo()
MsgBox "Hello World", vbOKOnly, "Foo!"
End Sub
I then saved this as a macro-enabled spreadsheet (C:\Temp\Book1.xlsm)
In Visual Studio I then created a C# console app and added the EPPlus package from NuGet. The main method looks like this:
static void Main(string[] args)
{
using (var pck = new ExcelPackage(new FileInfo(#"c:\temp\Book1.xlsm")))
{
pck.Save();
}
}
When I debug this it executes without issue.
Have you checked permissions on the folder you're saving to and forced a refresh of your EPPlus package?

Running macros through code on server: Wrong path to excel file?

In my application I open a .xlsm file with a macro (copies data to .xlsm file) and a .xlsx file that executes that macro. Let's say my files are called FileWithMacro.xlsm and FileThatExecutesMacro.xlsx. I need this application on a server but have developed it locally. To debug the application, I put my files to C:\Users\myUser\Documents\.
I'm opening the FileWithMacro.xlsm like this:
Excel.Application excel = new Excel.Application();
Excel.Workbook workbook = excel.Workbooks.Open(serverPath + "FileWithMacro.xlsm");
Excel._Worksheet worksheet = workbook.Sheets["FileThatExecutesMacro"];
After that, I call the method that runs the macro:
RunMacro(serverPath + "FileThatExecutesMacro.xlsx");
My method looks like this:
private static void RunMacro(string source)
{
Excel.Application excel = new Excel.Application();
Excel.Workbook workbook = excel.Workbooks.Open(source);
Excel._Worksheet worksheet = workbook.Sheets[1];
worksheet.Activate();
try
{
excelThatRunsMacro.Run("FileWithMacro.xlsm!MyMacro");
workbook.Save();
excelThatRunsMacro.Quit();
}
// and so on
}
Locally the macros work without any problems. When I change all the paths and copy the output of my code to the server (\\myServer\someUrl...), I'm getting the following exception:
'C:\Users\myServerUser\Documents\FileWithMacro.xlsm' could not be found.
Although I changed all my paths to the correct server location (and I am really sure that there is no local path in my code and in the macro anymore). I even deleted my bin and obj folders and rebuilt the project but that didn't change anything. I even created a new project and built it without using local paths but I got the same error. What am I doing wrong? Is excel.Run by default searching the macro in the Documents folder?
Or is the problem because of the line Windows("FileWithMacro.xlsm").Activate in my macro? When running the macro manually, it works fine. It just doesn't work when running it through the code.
I couldn't find out why I got the exception. However, I've found a workaround. Before executing the macro, I copy the FileWithMacro.xlsm to the location in the error message. When I then used the code like I've had it, I've got a message that the FileWithMacro.xlsm is already in use. To fix this, I just had to pass the Excel.Application to my method and use this instance instead of creating a new one:
private static void RunMacro(Excel.Application excel, string source)

Open Excel workbook in background using interop

I'm wanting to import data from an Excel workbook without actually displaying the open workbook.
I could have sworn I had used the following code on a previous project and it had worked:
var excelApp = new Excel.Application { Visible = false };
var workbook = excelApp.Workbooks.Open(filePath);
Unfortunately when the workbook opens it is displayed to the user which is unnecessary for this application.
I'm using Microsoft Excel 15.0 Object Library on this project when previously I think it was version 12 or 13. Maybe this is the problem, or is my memory fading and the code is incorrect?
I know this is old but just in case anybody still needs this answer...
excelApp.Visible = false;
(excelApp being the name of the variable used for the excel application)

Issue with an example in "How to transfer data to an Excel workbook "

http://support.microsoft.com/kb/306023 it's the first example: "Use Automation to Transfer Data Cell by Cell" Below are the variables I declared for the example.
Excel.Application m_objExcel;
Excel.Workbooks m_objBooks;
Excel._Workbook m_objBook;
Excel.Sheets m_objSheets;
Excel._Worksheet m_objSheet;
Excel.Range m_objRange;
string m_strSampleFolder = #"C:\VBtest\PRACTICEProgramming\INDIVIDUALprograms\EXCEL";
string m_objOpt = #"C:\VBtest\PRACTICEProgramming\INDIVIDUALprograms\EXCEL";
Excel.Font m_objFont;
Basically everything runs fine. The issue is when the app is running, I get an error message.
"COMException was unhandled
Excel cannot access 'EXCEL'. The document may be read-only or encrypted."
I'm thinking the value I declared for m_objOpt is declared wrong or it doesn't like the value. I tried creating a premade .XLS file but that doesn't work. I also tried putting a name for the xls but the add method wants to find the xls in the default path which I don't want.
I don't know what I can do to fix it.
Looks like you're missing the file extension at the end of m_objOpt... You can try to add .xls or .xlsx to it, or something else regarding the file extension.

threading problem (reading and writing to one excel file)

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)

Categories

Resources