How do I get the Path or the file name of workbook in the below code so that I can get the work book that is edited. I have used ExpertXLS – Excel Spreadsheet Library for .NET - C#/VB.NET here
using ExpertXls;
namespace IQC
{
public class CSFB
{
public static string GenerateTemplateForCurrentGridView(IQO[] items, string colname, int icol)
{
/*Some Code here*/
string pathSource = HttpContext.Current.Server.MapPath("~/pdf/ExportTemplate.xlsx");
ExpertXls.ExcelLib.ExcelWorkbook workbook = new ExpertXls.ExcelLib.ExcelWorkbook(#pathSource);
workbook.LicenseKey = Inq.Configuration.Settings.Value("ExpertPdfLicenseKey");
ExpertXls.ExcelLib.ExcelWorksheet ws = workbook.Worksheets["ImportTemplate"];
ExpertXls.ExcelLib.ExcelCellStyle Style1 = workbook.Styles.AddStyle("Style1");
Style1.Fill.FillType = ExpertXls.ExcelLib.ExcelCellFillType.SolidFill;
Style1.Fill.SolidFillOptions.BackColor = Color.Yellow;
foreach (string cols in colname.Split(','))
{
ws[cols].Style = Style1;
}
/*Some Code here*/
}
}
}
You may use Application.ActiveWorkbook.FullName if the workbook is active workbook. Also you can try using workbook.Path. Refer the link.
Adding below code worked. I have saved the worked book in "pathsource"
System.IO.FileStream fs = new FileStream(pathSource, FileMode.OpenOrCreate, FileAccess.ReadWrite);
string fileName = fs.Name;
try
{
workbook.Save(fs);
}
catch (Exception ex)
{
Logger.Error(" Error:", ex);
}
finally
{
workbook.Close();
}
Related
I am getting an error even when I dont update any anything.
when I run the code with epplus excel package anyone have a solution , i am using an xlsm file.
public void UpdateTheIntroExcelFile(IList<GeneralViewModel> Intro_Table, string Path)
{
try
{
if (Path != null)
{
ExcelPackage.LicenseContext = LicenseContext.Commercial;
var file = new FileInfo(fileName: Path);
using var ExPackage = new ExcelPackage(file);
var workSheet = ExPackage.Workbook.Worksheets[PositionID:0];
//workSheet.Cells[3, 30].Value = "Success";
ExPackage.Save();
}
}
catch (Exception ex)
{
ErrorMessage = ex.Message;
}
}
I need update custom Excel ribbon of working file without closing file from another Excel file.
I try make this task using Open XML SDK for Office.
Here class that export and import custom ribbon.
public static class OpenDocumentTools
{
public static bool ExportCustomRibbon(string fileName, string exportDir)
{
try
{
//Get RibbonExtensibilityPart
SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(fileName, true);
RibbonExtensibilityPart ribbon = spreadsheetDocument.RibbonExtensibilityPart;
//Clear directory
foreach (string fil in Directory.EnumerateFiles(exportDir).ToList())
File.Delete(fil);
//Processing images
foreach (ImagePart imagePart in ribbon.ImageParts.ToList())
{
Image img = Image.FromStream(imagePart.GetStream());
string[] arrPath = imagePart.Uri.OriginalString.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
string imageName = arrPath[arrPath.Length - 1];
img.Save(string.Format("{0}\\{1}", exportDir, imageName));
}
//Save ribbon xml
StreamWriter sw = File.CreateText(string.Format("{0}\\Ribbon.xml", exportDir));
sw.WriteLine(ribbon.CustomUI.OuterXml);
sw.Close();
return true;
}
catch(Exception ex)
{
return false;
}
}
public static bool ImportCustomRibbon(string fileName, string xmlFile, string importDir)
{
try
{
//Read xml content
string content = File.OpenText(xmlFile).ReadToEnd();
using (SpreadsheetDocument document = SpreadsheetDocument.Open(fileName, true))
{
//Get or create RibbonExtensibilityPart
RibbonExtensibilityPart ribbon = document.RibbonExtensibilityPart;
if (ribbon == null)
ribbon = document.AddRibbonExtensibilityPart();
//Load xml content to ribbon
ribbon.CustomUI = new CustomUI(content);
ribbon.CustomUI.Save();
//Remove image parts
foreach (ImagePart imagePart in ribbon.ImageParts.ToList())
ribbon.DeletePart(imagePart);
//Load images to ribbon
foreach (string fileNam in Directory.EnumerateFiles(importDir).ToList())
{
ImagePart imagePart = null;
switch (Path.GetExtension(fileNam))
{
case ".png":
imagePart = ribbon.AddImagePart(ImagePartType.Png, Path.GetFileNameWithoutExtension(fileNam));
break;
case ".jpeg":
imagePart = ribbon.AddImagePart(ImagePartType.Jpeg, Path.GetFileNameWithoutExtension(fileNam));
break;
default:
continue;
}
if (imagePart != null)
{
using (FileStream stream = new FileStream(fileNam, FileMode.Open))
{
stream.Position = 0;
imagePart.FeedData(stream);
}
ribbon.AddPart(imagePart, Path.GetFileNameWithoutExtension(fileNam));
}
}
}
return true;
}
catch(Exception ex)
{
return false;
}
}
}
Here calling code:
static void Main(string[] args)
{
bool res = OpenDocumentTools.ExportCustomRibbon(#"D:\15\Ribbon\Source.xlsm", #"D:\15\Ribbon\Export");
res = OpenDocumentTools.ImportCustomRibbon(#"D:\15\Ribbon\Dest.xlsm", #"D:\15\Ribbon\Export\Ribbon.xml", #"D:\15\Ribbon\Export");
}
When Excel-files are closed, code working fine. But if Excel-file is open, I have exception:
"The process cannot access the file 'D:\15\Ribbon\Dest.xlsm' because it is being used by another process.” This is occurred, when programm trying execute “using (SpreadsheetDocument document = SpreadsheetDocument.Open(fileName, true))”.
Does anybody know what way I can use for updating ribbon without closing file?
I am coding in C# .NET Core 2.2. I am trying to replace Excel Interop with EPPlusCore in my code for reliability and for portablilty. I have a series of invoices I am opening with EPPlus, but some of them throw a "Null Reference" exception when accessing the Workbook property of the Excel package.
This only happens when running the code without debugging it. When debugging, if I hover over the ExcelPackage item, it refreshes the reference to the Workbook and I am able to run the rest of the code.
public object[,] GetExcelDataEpplus(string filePath, int index,
bool sheetByName = false, string name = null, string password = null)
{
var remoteFileInfo = new FileInfo(filePath);
if (!remoteFileInfo.Exists)
{
throw new Exception("File does not exist: " + filePath);
}
var currentPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "temp-excel");
if (!Directory.Exists(currentPath))
{
Directory.CreateDirectory(currentPath);
}
var localFileInfo = new FileInfo(Path.Combine(currentPath, remoteFileInfo.Name));
if (!localFileInfo.Exists)
{
File.Copy(filePath, localFileInfo.FullName);
}
object[,] values = null;
try
{
if (!File.Exists(localFileInfo.FullName))
{
_logger.LogInformation(DbLog, "Cannot find file : " + localFileInfo.FullName);
return null;
}
else
{
_logger.LogInformation(DbLog, "Found file : " + localFileInfo.FullName);
}
_logger.LogInformation(DbLog, "Initializing EPPlus...");
using (var package = string.IsNullOrEmpty(password)
? new ExcelPackage(localFileInfo)
: new ExcelPackage(localFileInfo, password))
{
_logger.LogInformation(DbLog, "Opening Workbook...");
//todo Error Thrown Here
try
{
package.Workbook.FormulaParserManager.LoadFunctionModule(new ImporterFunctionModule());
}
catch (Exception e)
{
_logger.LogWarning(DbLog, e, $"Could not load workbook : Loading file again...");
try
{
System.Threading.Thread.Sleep(1000);
package.Workbook.FormulaParserManager.LoadFunctionModule(new ImporterFunctionModule());
}
catch (Exception ex)
{
_logger.LogError(DbLog, ex, "Could not load workbook");
throw;
}
}
var workbook = package.Workbook;
_logger.LogInformation(DbLog, $"Calculating formulas...");
workbook.Calculate();
_logger.LogInformation(DbLog, "Finding Worksheet...");
var worksheet = sheetByName ? workbook.Worksheets.FirstOrDefault(x => x.Name == name) : workbook.Worksheets[index];
if (worksheet == null)
{
throw new Exception($"Could not find worksheet : {name}");
}
_logger.LogInformation(DbLog, $"Reading from worksheet : {worksheet.Name}...");
var start = worksheet.Dimension.Start;
var end = worksheet.Dimension.End;
values = worksheet.Cells[start.Row, start.Column, end.Row, end.Column].ToMultiDimensionalArray();
}
}
catch (Exception e)
{
_logger.LogError(DbLog, e, $"GetExcelInvoiceDataEpplus from {filePath} ({localFileInfo.FullName})"); //todo propogate error
}
finally
{
File.Delete(localFileInfo.FullName);
}
var rowCount = values?.GetLength(0) ?? 0;
_logger.LogInformation(DbLog, $"EPPLus found {rowCount} rows in the spreadsheet");
return values;
}
On most files, this works correctly, and I get a multidimensional array of the values from the specified worksheet tab. However, on some files, it does not work and I am at a loss as to why.
The closest similar problem I've been able to find is this: https://github.com/JanKallman/EPPlus/issues/416
But if this is accurate, how would I know what worksheet names have bad references without accessing the workbook first?
I found the solution. The excel files that were having problems were ones that were larger than average.
The solution was just to wait longer for them.
try
{
package.Workbook.FormulaParserManager.LoadFunctionModule(new ImporterFunctionModule());
}
catch (Exception e)
{
for (var i=1; i < 6; i++)
{
_logger.LogWarning(DbLog, e, $"Could not load workbook : Loading file again (Attempt #{i})...");
try
{
System.Threading.Thread.Sleep(2000);
package.Workbook.FormulaParserManager.LoadFunctionModule(new ImporterFunctionModule());
break;
}
catch (Exception ex)
{
if (i < 5) continue;
_logger.LogError(DbLog, ex, "Could not load workbook after 5 attempts");
throw;
}
}
}
I've looked around, and for the most part I see examples for more complex problems than my own.
So, I've been suggested to use EPPLUS as opposed to EXCEL INTEROP because of the performance improvement. This is my first time using it, and the first time I've encountered memory streams, so I'm not exactly sure what's wrong here.
I'm trying to write to an Excel file and convert that excel file into a PDF. To do this, I installed through NUGET the following:
EPPLUS
EPPLUSExcel
This is my code:
if (DGVmain.RowCount > 0)
{
//Source
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "Excel Files|*.xls;*.xlsx";
openFileDialog.ShowDialog();
lblSuccess.Text = openFileDialog.FileName;
lblPathings = Path.ChangeExtension(openFileDialog.FileName, null);
int count = DGVmain.RowCount;
int current = 0;
int ballast = 0;
For each row in a DataGridView, perform write to Excel, then convert to PDF.
foreach (DataGridViewRow row in DGVmain.Rows)
{
//Drag
if (lblSuccess.Text == null)
return;
string drags = Convert.ToString(row.Cells[0].Value);
string dragsy = Convert.ToString(row.Cells[1].Value);
Persona = drag;
generateID();
//Initialize the Excel File
try
{
Here is where I expect something to be wrong:
using (ExcelPackage p = new ExcelPackage())
{
using (FileStream stream = new FileStream(lblSuccess.Text, FileMode.Open))
{
ballast++;
lblItem.Text = "Item #" + ballast;
p.Load(stream);
ExcelWorkbook WB = p.Workbook;
if (WB != null)
{
if (WB.Worksheets.Count > 0)
{
ExcelWorksheet WS = WB.Worksheets.First();
WS.Cells[82, 12].Value = drag13;
WS.Cells[84, 12].Value = "";
WS.Cells[86, 12].Value = 0;
//========================== Form
WS.Cells[95, 5].Value = drag26;
WS.Cells[95, 15].Value = drag27;
WS.Cells[95, 24].Value = drag28;
WS.Cells[95, 33].Value = drag29;
//========================== Right-Seid
WS.Cells[14, 31].Value = drag27;
WS.Cells[17, 31].Value = drag27;
}
}
Byte[] bin = p.GetAsByteArray();
File.WriteAllBytes(lblPathings, bin);
}
p.Save();
}
}
catch (Exception ex)
{
MessageBox.Show("Write Excel: " + ex.Message);
}
Separate method to convert to PDF, utilizing EPPLUSEXCEL and SpireXLS.
finally
{
ConvertToPdf(lblSuccess.Text, finalformat);
}
}
}
The compiler is not throwing any errors except the one mentioned in the title.
You already saved the ExcelPackage here:
Byte[] bin = p.GetAsByteArray();
So when you later try and save it again here:
p.Save();
the ExcelPackage is already closed. I.e. remove the Save() call in your code and you're good.
As part of a file storage migration project, I am trying to change some excel links in some excel workbooks to reflect the new file storage location.
I am using Winforms and C# in VS2017 RC to develop the solution that I intend to deploy.
In my solution; I am calling the ChangeLink method on the Excel Workbook object and passing in the old link, the new link and the Excel Link Type.
public string ProcessFile(string fileName)
{
// Private member variable and placeholder declarations
missingValue = Type.Missing;
string oldLink;
string newLink;
int splitLocation;
string stringToFind = "\\Finance";
//Open the specified Excel Workbook
Excel.Workbook excelWorkbook;
StringBuilder resultsOut = new StringBuilder();
if (MsOfficeHelper.IsPasswordProtected(fileName))
{
resultsOut = resultsOut.AppendLine("Password Protected - " + fileName);
}
else
{
// Open
excelWorkbook = excelApp.Workbooks.Open(Filename: fileName, UpdateLinks: false);
Array olinks = excelWorkbook.LinkSources(Excel.XlLink.xlExcelLinks) as Array;
if (olinks != null)
{
if (olinks.Length > 0)
{
resultsOut = resultsOut.AppendLine("Contains Links - " + fileName);
foreach (var olink in olinks)
{
oldLink = olink.ToString();
splitLocation = oldLink.IndexOf(stringToFind, 0);
newLink = "C:\\SteveTest\\" + oldLink.Substring(splitLocation + 1);
resultsOut = resultsOut.AppendLine(oldLink);
resultsOut = resultsOut.AppendLine(newLink);
try
{
excelWorkbook.ChangeLink(Name: oldLink, NewName: newLink, Type: Excel.XlLinkType.xlLinkTypeExcelLinks);
}
catch (Exception whoopsy)
{
MessageBox.Show(whoopsy.Message);
//throw;
}
}
}
}
excelWorkbook.Close(SaveChanges: false);
}
return resultsOut.ToString();
}
However, when I execute the ChangeLink method I get the following exception
Does anyone have any idea what is causing the exception?
Your considered responses will be greatly welcome.