Skip to content
This repository was archived by the owner on Mar 9, 2020. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 31 additions & 9 deletions EPPlus/ExcelAddress.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
using System.Globalization;
using System.Text;
using System.Text.RegularExpressions;
using OfficeOpenXml.FormulaParsing.Utilities;

namespace OfficeOpenXml
{
Expand Down Expand Up @@ -395,14 +396,19 @@ private string GetAddress()

if (!string.IsNullOrEmpty(_ws))
{
adr += string.Format("'{0}'!", _ws);
adr += GetWorksheetNameEscaped() + "!";
}
if (IsName)
adr += GetAddress(_fromRow, _fromCol, _toRow, _toCol);
else
adr += GetAddress(_fromRow, _fromCol, _toRow, _toCol, _fromRowFixed, _fromColFixed, _toRowFixed, _toColFixed);
return adr;
}

public string GetWorksheetNameEscaped()
{
return Regex.IsMatch(_ws, RegexConstants.SheetNameSingleQuotes) ? $"'{_ws.Replace("'", "''")}'" : _ws;
}
#endregion
protected ExcelCellAddress _start = null;
/// <summary>
Expand Down Expand Up @@ -889,8 +895,9 @@ internal enum AddressType
R1C1
}

internal static AddressType IsValid(string Address, bool r1c1=false)
internal static AddressType IsValid(string Address, out string normalizedAddress, bool r1c1 = false)
{
normalizedAddress = Address;
double d;
if (Address == "#REF!")
{
Expand Down Expand Up @@ -918,15 +925,25 @@ internal static AddressType IsValid(string Address, bool r1c1=false)
{
if (intAddress.Contains("[")) //Table reference
{
return string.IsNullOrEmpty(wb) ? AddressType.InternalAddress : AddressType.ExternalAddress;
}
else if (intAddress.Contains(","))
{
intAddress = intAddress.Substring(0, intAddress.IndexOf(','));
if (!string.IsNullOrEmpty(wb))
{
return AddressType.ExternalAddress;
}

normalizedAddress = NormalizeAddress(Address, ws, intAddress);
return AddressType.InternalAddress;
}
if (IsAddress(intAddress))

string addressToTest = intAddress.Contains(",") ? intAddress.Substring(0, intAddress.IndexOf(',')) : intAddress;
if (IsAddress(addressToTest))
{
return string.IsNullOrEmpty(wb) ? AddressType.InternalAddress : AddressType.ExternalAddress;
if (!string.IsNullOrEmpty(wb))
{
return AddressType.ExternalAddress;
}

normalizedAddress = NormalizeAddress(Address, ws, intAddress);
return AddressType.InternalAddress;
}
else
{
Expand All @@ -941,6 +958,11 @@ internal static AddressType IsValid(string Address, bool r1c1=false)
}
}

private static string NormalizeAddress(string fullAddress, string ws, string intAddress)
{
return fullAddress.StartsWith("!") ? fullAddress : string.IsNullOrEmpty(ws) ? intAddress : $"{ws}!{intAddress.ToUpperInvariant()}";
}

private static bool IsR1C1(string address)
{
if (address.StartsWith("!"))
Expand Down
10 changes: 8 additions & 2 deletions EPPlus/ExcelCellBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,10 @@ private static string ToR1C1(string part, int row, int col)
string p1 = ToR1C1_1(part.Substring(0, delim), row, col);
string p2 = ToR1C1_1(part.Substring(delim + 1), row, col);
if (p1.Equals(p2))
return p1;
{
return sh + p1;
}

return sh + p1 + ":" + p2;
}

Expand Down Expand Up @@ -209,7 +212,10 @@ private static string ToAbs(string part, int row, int col)
string p1 = ToAbs_1(part.Substring(0, delim), row, col, false);
string p2 = ToAbs_1(part.Substring(delim + 1), row, col, false);
if (p1.Equals(p2))
return p1;
{
return sh + p1;
}

return sh + p1 + ":" + p2;
}
else
Expand Down
19 changes: 5 additions & 14 deletions EPPlus/ExcelRangeBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -899,44 +899,31 @@ public void AutoFitColumns(double MinimumWidth, double MaximumWidth)
if (fnt.Italic) fs |= FontStyle.Italic;
if (fnt.Strike) fs |= FontStyle.Strikeout;
f = new Font(fnt.Name, fnt.Size, fs);
//f = new wm.Typeface(new System.Windows.Media.FontFamily(fnt.Name), fnt.Italic ? System.Windows.FontStyles.Italic : System.Windows.FontStyles.Normal, fnt.Bold ? System.Windows.FontWeights.Bold : System.Windows.FontWeights.Normal, System.Windows.FontStretches.Normal);

fontCache.Add(fntID, f);
}
var ind = styles.CellXfs[cell.StyleID].Indent;
var textForWidth = cell.TextForWidth;
var t = textForWidth + (ind > 0 && !string.IsNullOrEmpty(textForWidth) ? new string('_', ind) : "");
if (t.Length > 32000) t = t.Substring(0, 32000); //Issue
var size = g.MeasureString(t, f, 10000, StringFormat.GenericDefault);

//var ft = new wm.FormattedText(t, CultureInfo.CurrentCulture, w.FlowDirection.LeftToRight,
// f,
// styles.Fonts[fntID].Size, System.Windows.Media.Brushes.Black);
//var wd = ft.WidthIncludingTrailingWhitespace;


//var wi = ft.WidthIncludingTrailingWhitespace / (72 / 96D); //Typounit=72 DPI, WPF=96DPI
//var he = ft.Height / (72 / 96D);

double width;
double r = styles.CellXfs[cell.StyleID].TextRotation;
if (r <= 0)
{
//width = (wi + 15) / normalSize;
width = (size.Width + 5) / normalSize;
}
else
{
r = (r <= 90 ? r : r - 90);
width = (((size.Width - size.Height) * Math.Abs(System.Math.Cos(System.Math.PI * r / 180.0)) + size.Height) + 5) / normalSize;
//width = (((wi - he) * Math.Abs(Math.Cos(Math.PI * r / 180.0)) + he) + 15) / normalSize;
//width= (((size.Width-size.Height) * Math.Abs(Math.Cos(Math.PI * r / 180.0)) + size.Height) +15) / normalSize;
}

foreach (var a in afAddr)
{
if (a.Collide(cell) != eAddressCollition.No)
{
//width += 2.8;
width += 2.25;
break;
}
Expand Down Expand Up @@ -1110,6 +1097,10 @@ private static string GetDateText(DateTime d, string format, ExcelNumberFormatXm
{
return d.ToLongTimeString();
}
else if (nf.SpecialDateFormat == ExcelNumberFormatXml.ExcelFormatTranslator.eSystemDateFormat.SystemShortDate)
{
return d.ToShortDateString();
}
if (format == "d" || format == "D")
{
return d.Day.ToString();
Expand Down
2 changes: 1 addition & 1 deletion EPPlus/ExcelWorkbook.cs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ internal void GetDefinedNames()
nameWorksheet=Worksheets[localSheetID + _package._worksheetAdd];
}

var addressType = ExcelAddressBase.IsValid(fullAddress);
var addressType = ExcelAddressBase.IsValid(fullAddress, out _);
ExcelRangeBase range;
ExcelNamedRange namedRange;

Expand Down
2 changes: 1 addition & 1 deletion EPPlus/FormulaParsing/ExcelAddressCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,4 @@ public void Clear()
}

}
}
}
4 changes: 2 additions & 2 deletions EPPlus/FormulaParsing/LexicalAnalysis/TokenFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,10 +152,10 @@ public Token Create(IEnumerable<Token> tokens, string token, string worksheet)
{
return new Token(token, TokenType.Enumerable);
}
var at = OfficeOpenXml.ExcelAddressBase.IsValid(token, _r1c1);
var at = OfficeOpenXml.ExcelAddressBase.IsValid(token, out string normalizedToken, _r1c1);
if (at==ExcelAddressBase.AddressType.InternalAddress)
{
return new Token(token.ToUpper(CultureInfo.InvariantCulture), TokenType.ExcelAddress);
return new Token(normalizedToken, TokenType.ExcelAddress);
}
else if (at == ExcelAddressBase.AddressType.R1C1)
{
Expand Down
1 change: 1 addition & 0 deletions EPPlus/FormulaParsing/Utilities/RegexConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public static class RegexConstants
//Changed JK 26/2-2013
public const string ExcelAddress = @"^(('[^/\\?*\[\]]{1,31}'|[A-Za-z_]{1,31})!)?[\$]{0,1}([A-Z]|[A-Z]{1,3}[\$]{0,1}[1-9]{1}[0-9]{0,7})(\:({0,1}[A-Z]|[A-Z]{1,3}[\$]{0,1}[1-9]{1}[0-9]{0,7})){0,1}$";
//public const string ExcelAddress = @"^([\$]{0,1}([A-Z]{1,3}[\$]{0,1}[0-9]{1,7})(\:([\$]{0,1}[A-Z]{1,3}[\$]{0,1}[0-9]{1,7}){0,1})|([\$]{0,1}[A-Z]{1,3}\:[\$]{0,1}[A-Z]{1,3})|([\$]{0,1}[0-9]{1,7}\:[\$]{0,1}[0-9]{1,7}))$";
public const string SheetNameSingleQuotes = @"^[A-Z]{1,3}[1-9]{1}[0-9]{0,7}$|^R-?\d*C-?\d*$|[\s()'$,;\-{}!]";
public const string Boolean = @"^(true|false)$";
public const string Decimal = @"^[0-9]+\.[0-9]+$";
public const string Integer = @"^[0-9]+$";
Expand Down
6 changes: 4 additions & 2 deletions EPPlus/Style/XmlAccess/ExcelNumberFormatXml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -203,14 +203,16 @@ internal enum eSystemDateFormat
None,
SystemLongDate,
SystemLongTime,
Conditional
Conditional,
SystemShortDate,
}
internal ExcelFormatTranslator(string format, int numFmtID)
{
if (numFmtID == 14)
{
NetFormat = NetFormatForWidth = "d";
NetFormat = NetFormatForWidth = "";
NetTextFormat = NetTextFormatForWidth = "";
SpecialDateFormat = eSystemDateFormat.SystemShortDate;
DataType = eFormatType.DateTime;
}
else if (format.Equals("general",StringComparison.OrdinalIgnoreCase))
Expand Down
32 changes: 30 additions & 2 deletions EPPlusTest/ExcelCellBaseTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ public void UpdateFormulaReferencesReferencingADifferentSheetIsNotUpdated()
[TestMethod]
public void UpdateFormulaSheetReferences()
{
var result = ExcelCellBase.UpdateFormulaSheetReferences("5+'OldSheet'!$G3+'Some Other Sheet'!C3+SUM(1,2,3)", "OldSheet", "NewSheet");
Assert.AreEqual("5+'NewSheet'!$G3+'Some Other Sheet'!C3+SUM(1,2,3)", result);
var result = ExcelCellBase.UpdateFormulaSheetReferences("5+OldSheet!$G3+'Some Other Sheet'!C3+SUM(1,2,3)", "OldSheet", "NewSheet");
Assert.AreEqual("5+NewSheet!$G3+'Some Other Sheet'!C3+SUM(1,2,3)", result);
}

[TestMethod]
Expand Down Expand Up @@ -86,6 +86,34 @@ public void UpdateFormulaSheetReferencesEmptyNewSheetThrowsException()
{
ExcelCellBase.UpdateFormulaSheetReferences("formula", "sheet1", string.Empty);
}

[TestMethod]
public void UpdateFormulaSheetReferencesToSheetNameWithSpace()
{
var result = ExcelCellBase.UpdateFormulaSheetReferences("Sheet1!A1", "Sheet1", "Sheet 1");
Assert.AreEqual("'Sheet 1'!A1", result);
}

[TestMethod]
public void UpdateFormulaSheetReferencesToSheetNameWithSpecialChars()
{
var result = ExcelCellBase.UpdateFormulaSheetReferences("Sheet1!A1", "Sheet1", "(Sheet)'1!");
Assert.AreEqual("'(Sheet)''1!'!A1", result);
}

[TestMethod]
public void UpdateFormulaSheetReferencesToSheetNameWithA1Notation()
{
var result = ExcelCellBase.UpdateFormulaSheetReferences("Sheet1!A1", "Sheet1", "B1048576");
Assert.AreEqual("'B1048576'!A1", result);
}

[TestMethod]
public void UpdateFormulaSheetReferencesToSheetNameWithR1C1Notation()
{
var result = ExcelCellBase.UpdateFormulaSheetReferences("Sheet1!A1", "Sheet1", "RC");
Assert.AreEqual("'RC'!A1", result);
}
#endregion
}
}
41 changes: 41 additions & 0 deletions EPPlusTest/FormulaParsing/FormulaR1C1Test.cs
Original file line number Diff line number Diff line change
Expand Up @@ -234,5 +234,46 @@ public void OutOfRangeCol()
Assert.AreEqual("A3", _sheet.Cells["B3"].Formula);

}

[TestMethod]
public void SheetNameTest()
{
const string formulaR1C1 = "SUM(Test2!R[-4]C[-4]:R[-1]C[-1])";
_sheet.Cells[5, 5].FormulaR1C1 = formulaR1C1;
string formula = _sheet.Cells[5, 5].Formula;
Assert.AreEqual("SUM(Test2!A1:D4)", formula);
}

[TestMethod]
public void TranslateToR1C1Test1()
{
const string formula = "SUM(Sheet1!A:A)";
var formulaR1C1 = ExcelCellBase.TranslateToR1C1(formula, 1,2);
Assert.AreEqual("SUM(Sheet1!C[-1])",formulaR1C1);
}

[TestMethod]
public void TranslateToR1C1Test2()
{
const string formula = "SUM(Sheet1!1:1)";
var formulaR1C1 = ExcelCellBase.TranslateToR1C1(formula, 2,1);
Assert.AreEqual("SUM(Sheet1!R[-1])",formulaR1C1);
}

[TestMethod]
public void TranslateFromR1C1Test1()
{
const string formulaR1C1 = "SUM(Sheet1!C[-1])";
var formula = ExcelCellBase.TranslateFromR1C1(formulaR1C1, 1,2);
Assert.AreEqual("SUM(Sheet1!A:A)", formula);
}

[TestMethod]
public void TranslateFromR1C1Test2()
{
const string formulaR1C1 = "SUM(Sheet1!R[-1])";
var formula = ExcelCellBase.TranslateFromR1C1(formulaR1C1, 2,1);
Assert.AreEqual("SUM(Sheet1!1:1)", formula);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ public void CreateShouldCreateExcelRangeOnOtherSheetAsExcelAddressToken()
var input = "ws!A1:B15";
var token = _tokenFactory.Create(Enumerable.Empty<Token>(), input);
Assert.AreEqual(TokenType.ExcelAddress, token.TokenType);
Assert.AreEqual("WS!A1:B15", token.Value);
Assert.AreEqual("ws!A1:B15", token.Value);
}

[TestMethod]
Expand Down
20 changes: 20 additions & 0 deletions EPPlusTest/Issues.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2387,5 +2387,25 @@ public void Issue387()
workbook.Names.Add("Q0", cells);
}
}
[TestMethod]
public void Issue333()
{
using (var package = new ExcelPackage())
{
var ws = package.Workbook.Worksheets.Add("TextBug");
ws.Cells["A1"].Value = new DateTime(2019, 3, 7);
ws.Cells["A1"].Style.Numberformat.Format = "mm-dd-yy";

Assert.AreEqual("2019-03-07", ws.Cells["A1"].Text);
}
}
[TestMethod]
public void Issue445()
{
ExcelPackage p = new ExcelPackage();
ExcelWorksheet ws = p.Workbook.Worksheets.Add("AutoFit"); //<-- This line takes forever. The process hangs.
ws.Cells[1, 1].Value = new string('a', 50000);
ws.Cells[1, 1].AutoFitColumns();
}
}
}