EPPlus Excel not opening after applying conditional formatting - c#

I am generating excel with EPPlus and it was opening but the moment i applied condition formatting excel generation slow and file is opening in my pc but not opening in another pc.
For conditional formatting right font color is coming. my objective of conditional formatting is if cell value >-1 then color will be Green and if cell value is <0 then color will be red. The code i got from google search for conditional formatting which is working fine when i open excel file in my pc but when same excel open in another pc there a error is coming for conditional formatting.
Here i am sharing my conditional formatting code. please have a look and tell me does it applied properly or code is not right one.
#region Conditional Formatting
address = new ExcelAddress(AvgPeriod3 + row.ToString());
_statement1 = "=AND($" + address + ">-1)";
condition = ws.ConditionalFormatting.AddExpression(address);
condition.Formula = _statement1;
condition.Style.Font.Color.Color = System.Drawing.Color.Green;
address = new ExcelAddress(AvgPeriod3 + row.ToString());
_statement1 = "=AND($" + address + "<0)";
condition = ws.ConditionalFormatting.AddExpression(address);
condition.Formula = _statement1;
condition.Style.Font.Color.Color = System.Drawing.Color.Red;
#endregion
if the above code is not right one for my requirement then please suggest me what to change in the above code.
another things not clear that excel file is opening in my pc but throwing error regarding conditional formatting when try to open in another pc. excel version is more less same or close in two pc.
Thanks

This way you can add conditional formatting.
string _StartPeriod = "", _EndPeriod = "";
//_EarningID_Periods
for (int p = 0; p <= _EarningID_Periods.Count - 1; p++)
{
Period = _EarningID_Periods[p].NewPeriod.Replace("A", "").Replace("E", ""); //ds.Tables[1].Rows[p]["old_Periods"].ToString().Replace("A", "").Replace("E", "");
_StartPeriod = listOfCell.Where(a => a.EarningsType == "NEW"
&& a.PeriodType == "DELTA_PERCENTAGE_PERIOD" && a.Period.Replace("A", "").Replace("E", "") == Period
).FirstOrDefault().CoorDinate + "4";
_EndPeriod = listOfCell.Where(a => a.EarningsType == "NEW"
&& a.PeriodType == "DELTA_ABSOLUTE" && a.Period.Replace("A", "").Replace("E", "") == Period
).FirstOrDefault().CoorDinate + row.ToString();
if (_StartPeriod != "" && _EndPeriod != "")
{
ExcelAddress formatRangeAddress = new ExcelAddress(_StartPeriod + ":" + _EndPeriod);
var cond1 = ws.ConditionalFormatting.AddLessThan(formatRangeAddress);
cond1.Style.Font.Color.Color = CSMUtils._RedColor;
cond1.Formula = "0";
formatRangeAddress = new ExcelAddress(_StartPeriod + ":" + _EndPeriod);
var cond2 = ws.ConditionalFormatting.AddGreaterThan(formatRangeAddress);
cond2.Style.Font.Color.Color = CSMUtils._GreenColor; //CSMUtils.SetRGBColor(0, 97, 0);
cond2.Formula = "0";
}
}

Related

How do i working with Arrays in a While loop?

I have tried to wipe this data while trying to export a database into my program.
The basic problem is that I do not know why he can not use LIKE in my SQL statement.
So I wanted to catch all DataRows and write them into an array, which I can edit later.
The program throws an exception:
Error message: System.IndexOutOfRangeException: "The index was outside the array area."
If I did something unusual or wrong in my Post I sincerely apologies, this is my first entry in this forum.
Code:
public void TestQuery()
{
string file = #"C:\Users\Michael\Downloads\7z1900-x64.msi";
// Get the type of the Windows Installer object
Type installerType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
// Create the Windows Installer object
WindowsInstaller.Installer installer = (WindowsInstaller.Installer)Activator.CreateInstance(installerType);
// Open the MSI database in the input file
Database database = installer.OpenDatabase(file, 0);
// Open a view on the Property table for the version property
View view = database.OpenView("SELECT * FROM `File`");
// Execute the view query
view.Execute(null);
// Get the record from the view
Record record = view.Fetch();
int i = 1;
string[] sreturns = new string[60];
while (record != null)
{
Console.WriteLine("Ausgabe: " + record.get_StringData(0) + '=' + record.get_StringData(1) + '=' + record.get_StringData(2) + '=' + record.get_StringData(3));
record = view.Fetch();
sreturns[i] = record.get_StringData(0).ToString();
i++;
}
}
First thing I see is that you're starting at 1, while (C#) arrays are 0-based.
In you screenshot I see that i is 60, so that would be the problem. Index 60 doesn't actually exist in your array, as it goes from 0 to 59.
You can add i < sreturns.Length to make sure you are in the array range.
Also, make sure you start with i = 0 and not 1.
int i = 0;
string[] sreturns = new string[60];
while (record != null && i < sreturns.Length)
{
Console.WriteLine("Ausgabe: " + record.get_StringData(0) + '=' + record.get_StringData(1) + '=' + record.get_StringData(2) + '=' + record.get_StringData(3));
record = view.Fetch();
sreturns[i] = record.get_StringData(0).ToString();
i++;
}
Why not using a list instead of an array?
List<string> sreturns = new List<string>();
while (record != null)
{
try
{
Console.WriteLine("Ausgabe: " + record.get_StringData(0) + '=' + record.get_StringData(1) + '=' + record.get_StringData(2) + '=' + record.get_StringData(3));
record = view.Fetch();
var result = record.get_StringData(0);
sreturns.Add(result.ToString());
}
catch (Exception e)
{
Console.WriteLine("No record...");
}
}
This way you dont need to worry about the array size - its maintainable -efficient - and if in the future the size change you don't have to worry about it.
List documentation here
What is the query with LIKE that you have tried? The following should work:
SELECT * FROM File WHERE FileName LIKE '%.exe' OR FileName LIKE '%.msi'
EDIT: On further investigation (https://learn.microsoft.com/en-us/windows/win32/msi/sql-syntax), the documentation seems to imply that the LIKE operator is not supported. But you could start off with an IS NOT NULL and do more complex filtering in the loop, like you're doing.
EDIT 2, expanding on Alex Leo's answer.
List<string> sreturns = new List<string>();
while (record != null)
{
Console.WriteLine("Ausgabe: " + record.get_StringData(0) + '=' + record.get_StringData(1) + '=' + record.get_StringData(2) + '=' + record.get_StringData(3));
var result = record.get_StringData(0);
if(!string.IsNullOrWhiteSpace(result) && (result.EndsWith(".exe") || result.EndsWith(".msi")))
{
sreturns.Add(result.ToString());
}
record = view.Fetch();
}
Note that the view.Fetch() inside the while loop has been moved to the end, or you would skip the first record, as well as get another null reference when the last record has already been read, but the while loop executes one more time.

Convert PDF to TIFF using ImageMagick & C#

I have an existing program that does some processing a .pdf file and splitting it into multiple .pdf files based on looking for barcodes on the pages.
The program uses ImageMagick and C#.
I want to change it from outputting pdfs to outputting tifs. Look for the comment in the code below for where I would guess the change would be made.
I included the ImageMagick tag because someone might offer a commandline option that someone else can help me convert to C#.
private void BurstPdf(string bigPdfName, string targetfolder)
{
bool outputPdf = true; // change to false to output tif.
string outputExtension = "";
var settings = new MagickReadSettings { Density = new Density(200) };
string barcodePng = Path.Combine("C:\TEMP", "tmp.png");
using (MagickImageCollection pdfPageCollection = new MagickImageCollection())
{
pdfPageCollection.Read(bigPdfName, settings);
int inputPageCount = 0;
int outputPageCount = 0;
int outputFileCount = 0;
MagickImageCollection resultCollection = new MagickImageCollection();
string barcode = "";
string resultName = "";
IBarcodeReader reader = new BarcodeReader();
reader.Options.PossibleFormats = new List<BarcodeFormat>();
reader.Options.PossibleFormats.Add(BarcodeFormat.CODE_39);
reader.Options.TryHarder = false;
foreach (MagickImage pdfPage in pdfPageCollection)
{
MagickGeometry barcodeArea = getBarCodeArea(pdfPage);
IMagickImage barcodeImg = pdfPage.Clone();
barcodeImg.ColorType = ColorType.Bilevel;
barcodeImg.Depth = 1;
barcodeImg.Alpha(AlphaOption.Off);
barcodeImg.Crop(barcodeArea);
barcodeImg.Write(barcodePng);
inputPageCount++;
using (var barcodeBitmap = new Bitmap(barcodePng))
{
var result = reader.Decode(barcodeBitmap);
if (result != null)
{
// found a first page because it has bar code.
if (result.BarcodeFormat.ToString() == "CODE_39")
{
if (outputFileCount != 0)
{
// write out previous pages.
if (outputPdf) {
outputExtension = ".pdf";
} else {
// What do I put here to output a g4 compressed tif?
outputExtension = ".tif";
}
resultName = string.Format("{0:D4}", outputFileCount) + "-" + outputPageCount.ToString() + "-" + barcode + outputExtension;
resultCollection.Write(Path.Combine(targetfolder, resultName));
resultCollection = new MagickImageCollection();
}
barcode = standardizePhysicalBarCode(result.Text);
outputFileCount++;
resultCollection.Add(pdfPage);
outputPageCount = 1;
}
else
{
Console.WriteLine("WARNING barcode is not of type CODE_39 so something is wrong. check page " + inputPageCount + " of " + bigPdfName);
if (inputPageCount == 1)
{
throw new Exception("barcode not found on page 1. see " + barcodePng);
}
resultCollection.Add(pdfPage);
outputPageCount++;
}
}
else
{
if (inputPageCount == 1)
{
throw new Exception("barcode not found on page 1. see " + barcodePng);
}
resultCollection.Add(pdfPage);
outputPageCount++;
}
}
if (File.Exists(barcodePng))
{
File.Delete(barcodePng);
}
}
if (resultCollection.Count > 0)
{
if (outputPdf) {
outputExtension = ".pdf";
} else {
// What do I put here to output a g4 compressed tif?
outputExtension = ".tif";
}
resultName = string.Format("{0:D4}", outputFileCount) + "-" + outputPageCount.ToString() + "-" + barcode + outputExtension;
resultCollection.Write(Path.Combine(targetfolder, resultName));
outputFileCount++;
}
}
}
[EDIT] The above code is what I am using (which some untested modifications) to split a .pdf into other .pdfs. I want to know how to modify this code to output tiffs. I put a comment in the code where I think the change would go.
[EDIT] So encouraged by #fmw42 I just ran the code with the .tif extension enabled. Looks like it did convert to a .tif, but the tif is not compressed. I am surprised that IM just configures the output based on the extension name of the file. Handy I guess, but just seems a little loose.
[EDIT] I figured it out. Although counter-intuitive ones sets the compression on the read of the file. I am reading a .pdf but I set the compression to Group for like this:
var settings = new MagickReadSettings { Density = new Density(200), Compression = CompressionMethod.Group4 };
The thing I learned was that simply naming the output file .tif tells IM to output a tif. That is a handy way to do it, but it just seems sloppy.

EPPlus Dispose Doesn't Work

I want to create workbook and then write data using EPPlus. When I create new workbook, it can create successfully. But when I want to write some data to that worksheet, it failed and error says
The process cannot access the file 'filename' because it is being
used by another process.
I have disposed previous ExcelPackage but the error still show when I write data.
//Create new Workbook
private void PengisianBaruBW_DoWork(object sender, DoWorkEventArgs e)
{
this.Invoke(new MethodInvoker(delegate
{
SetPengisianBtn.Enabled = false;
}));
FileInfo filePath = new FileInfo("D:\\Data Pengisian SLA Surabaya\\" + day + "_" + date + ".xlsx");
if (File.Exists(filePath.ToString()))
{
File.Delete(filePath.ToString());
}
using (ExcelPackage pck = new ExcelPackage(filePath))
{
var schedule = pck.Workbook.Worksheets.Add("Schedule");
var cart = pck.Workbook.Worksheets.Add("Cartridge");
var unsche = pck.Workbook.Worksheets.Add("Unschedule");
var rekap = pck.Workbook.Worksheets.Add("Rekap");
//My Code here
pck.SaveAs(filePath);
pck.Dispose(); //I have disposed ExcelPakcage here
}
}
//Write Data to Excel File
private void PrintScheduleBtn_Click(object sender, EventArgs e)
{
if (StaffATB.Text != "" && HelperTeamATB.Text != "" && StaffBTB.Text != "" && HelperTeamBTB.Text != "" && StaffCTB.Text != "" && HelperTeamCTB.Text != "" && StaffDTB.Text != "" && HelperTeamDTB.Text != "")
{
DialogResult dialogResult = MessageBox.Show("Apakah Anda yakin ingin menyimpan jadwal pengisian ?", "", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
{
FileInfo file = new FileInfo("D:\\Data Pengisian SLA Surabaya\\" + day + "_" + date + ".xlsx");
using (ExcelPackage pck = new ExcelPackage(file)) //error here
{
var rekap = pck.Workbook.Worksheets["Rekap"];
var data = pck.Workbook.Worksheets["Data"];
//my code to write data here
pck.SaveAs(file);
pck.Dispose();
}
}
}
else
{
MessageBox.Show("Silakan isi PIC terlebih dahulu !");
}
}
I have added this code to check whether my excel file is active or not. But the error still exsit. I set breakpoint and I see that stream value is null that indicate that my excel file is close. But why the error still exists ? Can anyone help me ?
string file = "D:\\Data Pengisian SLA Surabaya\\" + day + "_" + date + ".xlsx";
var path = Path.Combine(Path.GetTempPath(), "D:\\Data Pengisian SLA Surabaya\\" + day + "_" + date + ".xlsx");
var tempfile = new FileInfo(path);
FileStream stream = null;
try
{
stream = tempfile.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
}
catch (IOException)
{
}
finally
{
if (stream != null)
stream.Close();
}
I simplified your snippet for testing. It all worked as it should. Are you sure there is no other cause of the file access problem, like a virus scanner, backup program etc. since you also have another question with the same basic problem.
Take a look at the snippet below, try it and see if this one works. If not the problem is not in the code.
FileInfo filePath = new FileInfo("ExcelDemo.xlsx");
if (File.Exists(filePath.ToString()))
{
File.Delete(filePath.ToString());
}
using (ExcelPackage pck = new ExcelPackage(filePath))
{
var schedule = pck.Workbook.Worksheets.Add("Schedule");
var cart = pck.Workbook.Worksheets.Add("Cartridge");
var unsche = pck.Workbook.Worksheets.Add("Unschedule");
var rekap = pck.Workbook.Worksheets.Add("Rekap");
pck.SaveAs(filePath);
}
using (ExcelPackage pck = new ExcelPackage(filePath))
{
var rekap = pck.Workbook.Worksheets["Rekap"];
var schedule = pck.Workbook.Worksheets["Schedule"];
rekap.Cells[4, 1].Value = "Added data";
schedule.Cells[4, 1].Value = "Added data";
pck.SaveAs(filePath);
}
As already stated, the basic code should work just fine. However, looking at your code, I sense that you are using some kind of BackgroundWorker (PengisianBaruBW_DoWork name suggests this).
If so, you might run into accessing the same file from another thread (PengisianBaruBW_DoWork executes in parallel with PrintScheduleBtn_Click).
To help you more, you should add where (what line) do you receive this error and the call stack.
[Edit]
Based on additional comments, I think of one of these scenarios:
1) PengisianBaruBW_DoWork gets called many times and sometimes it happens to do work with the file, while PrintScheduleBtn_Click is trying to do work with the same file
2) An unhandled exception in _DoWork might get swallowed and leave the file opened (highly improbable since you have a disposable context).
Either way, put a breakpoint at the start of your _DoWork and one at beginning of PrintScheduleBtn_Click and use step over (F10).
I know this an old post, but it never got solved. I ran into the same problem, but i think i found the solution for it (at least it unlocked my excel file):
excelPackage.Dispose();
excelPackage = null;
GC.Collect();

How to override a specific line in a text file in c#

I have the following situation. I am creating a quiz game in c# visual studio and want to create a Register and Login forms. When a user registers a new account the text file will store their username and password and will set the high score to 0. Each line in the text file looks like that: username;password;highscore. ';' is the delimiter. I have created a new project to create a practice login/ register form. Here is my code for the register form:
private void btnRegister_Click(object sender, EventArgs e)
{
if (txtPassword.Text == txtConfirmPassword.Text)
{
string newAccount = txtName.Text + ";" + txtConfirmPassword.Text + ";" + "0";
TextWriter account = new StreamWriter("../../TextFile/LogonDetails.txt", true);
account.WriteLine(newAccount);
account.Close();
MessageBox.Show("Account created");
}
and here is my code for the login form
string line = "";
StreamReader myReader = new StreamReader("../../TextFile/LogonDetails.txt");
string[] accounts = new string[900000]; int value = 0;
while ((line=myReader.ReadLine()) != null)
{
string[] data = line.Split(';');
if ((data[0] == txtLoginName.Text) && (data[1] == txtLoginPassword.Text) && (int.Parse(data[2]) > int.Parse(txtScore.Text)))
{
value = 1;
break;
}
if ((data[0] == txtLoginName.Text) && (data[1] == txtLoginPassword.Text) && (int.Parse(data[2]) < int.Parse(txtScore.Text)))
{
value = 2;
break;
}
else
{
value = 3;
}
}
if (value == 1)
{
MessageBox.Show("Your score remains the same");
}
else if (value == 2)
{
string updatedAccount = txtLoginName.Text + ";" + txtLoginPassword.Text + ";" + txtScore;
TextWriter textAccounts = new StreamWriter("../../TextFile/LogonDetails.txt");
textAccounts.WriteLine(updatedAccount);
textAccounts.Close();
}
else if (value == 3)
{
MessageBox.Show("Account not found");
}
}
So my question is how can I override the line stored in the text file if in this case 'txtScore' is greater than data[2]? I have tried creating a new line each time the score is greater but that seems inefficient. Is there a way that i can override the line to change the score value? Any help is greatly appreciated
If the file is not that long you can do something like this:
String fileName = #"C:\LogonDetails.txt";
var data = File
.ReadLines(fileName)
.Select(line => line.Split(';'))
.Select(items => {
if ((items[0] == txtLoginName.Text) &&
(items[1] == txtLoginName.Text) &&
(int.Parse(items[2]) < int.Parse(txtScore.Text)))
items[2] = int.Parse(txtScore.Text);
return items;
})
.ToList(); // materialize in oreder to prevent file read/write collision
File.WriteAllLines(fileName, data);
There is no straightforward way to target a specific line in a text file to update the contents on that line. I would suggest storing your information in an XML (structured data) format; .NET already has the capabilities built in for reading and writing to specific nodes in an XML file.
If you don't want to do that, then my suggestion would be that you load all the lines from the text file into memory as instances of, e.g. a User class that has as properties your username, password, and score, and then write them all back out to your data file all at once with any updates to the scores.
By the way, it's generally not a good idea to store passwords in plain text, so I would hope you're at least employing a hashing algorithm.
Well, based on your question you know the line number, so do something like this:
var lines = File.ReadAllLines(#"path to file");
if (lines.Contains("1234"))
{
lines[Array.IndexOf(lines, "1234")] = "new york";
}
File.WriteAllLines(#"path to file", lines);
try like this.

Gem Box Spreadsheet msi error

I have to do a Excel Manager with C# and i choose to use Gem Box Spreadsheet Free
var ef = new ExcelFile();
ef = ExcelFile.Load(File_Lettura);
ExcelWorksheet ws = ef.Worksheets.ActiveWorksheet;
int riga = 13;
string s = (ws.Cells["B6"]).ToString();
string[] r = s.Split('-');
int c = 0;
while (ws.Cells["B"+riga.ToString()].Value != null)
{
if (ws.Cells["F"+riga.ToString()].Value.ToString() != "")
{
// add row
dgwFile.Rows.Add();
dgwFile.Rows[c].Cells[0].Value = r[0] + "-" + r[1] + "-" + ws.Cells["B"+riga.ToString()].Value.ToString();
dgwFile.Rows[c].Cells[1].Value = ws.Cells["D" + riga.ToString()].Value.ToString() + ws.Cells["G" + riga.ToString()].Value.ToString() + ws.Cells["H" + riga.ToString()].Value.ToString() + ws.Cells["I" + riga.ToString()].Value.ToString();
dgwFile.Rows[c].Cells[2].Value = ws.Cells["F" + riga.ToString()].Value.ToString();
dgwFile.Rows[c].Cells[3].Value = "0";
c++;
}
riga++;
}
VS give me a problem at the first "IF" with error :
An unhandled exception of type 'System.NullReferenceException'
occurred.
I think the wrong rows are the first 3
thanks in advance Smile | :)
i've also tried like it
ExcelFile ef = ExcelFile.Load(File_Lettura);
ExcelWorksheet ws = ef.Worksheets.ActiveWorksheet;
I don't believe the first 3 lines are the problem, however in order to be 100% sure you would need to specify exactly where the exception is thrown.
Nevertheless I presume one of the ExcelCell's that you are targeting is null.
So try this:
while (ws.Cells["B"+riga.ToString()] != null &&
ws.Cells["B"+riga.ToString()].Value != null)
{
if (ws.Cells["F"+riga.ToString()] != null &&
ws.Cells["F"+riga.ToString()].Value != null)
{

Categories

Resources