Skip to content

Commit

Permalink
Add ReferenceArea.TryParseA1 method
Browse files Browse the repository at this point in the history
In many cases, it's possible that text might be a A1 reference or not.
It could be using defined name (.e.g `Sheet!Name`). In such situations,
it's better to use Try method instead of catching exception.
  • Loading branch information
jahav committed Oct 3, 2024
1 parent 22786fe commit e812c0e
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 3 deletions.
23 changes: 23 additions & 0 deletions src/ClosedXML.Parser.Tests/ReferenceAreaTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,29 @@ public void ParseA1_throws_on_non_references()
Assert.Throws<ParsingException>(() => ReferenceArea.ParseA1("HELLO"));
}

[Theory]
[MemberData(nameof(ParseA1TestCases))]
public void TryParseA1_parses_cell_area_or_rowspan_or_colspan(string text, ReferenceArea expectedReference)
{
var success = ReferenceArea.TryParseA1(text, out var area);
Assert.True(success);
Assert.Equal(expectedReference, area);
}

[Fact]
public void TryParseA1_requires_argument()
{
Assert.Throws<ArgumentNullException>(() => ReferenceArea.TryParseA1(null!, out _));
}

[Fact]
public void ParseA1_returns_false_on_non_references()
{
var success = ReferenceArea.TryParseA1("HELLO", out var area);
Assert.False(success);
Assert.Equal(default, area);
}

public static IEnumerable<object[]> ParseA1TestCases
{
get
Expand Down
34 changes: 31 additions & 3 deletions src/ClosedXML.Parser/ReferenceArea.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using ClosedXML.Parser.Rolex;
using System;
using System.Text;
using JetBrains.Annotations;

namespace ClosedXML.Parser;

Expand Down Expand Up @@ -120,8 +121,11 @@ public string GetDisplayStringR1C1()
/// </list>
/// Doesn't allow any whitespaces or extra values inside.
/// </summary>
/// <exception cref="ParsingException">Invalid input.</exception>
public static ReferenceArea ParseA1(string text)
/// <param name="text">Text to parse.</param>
/// <param name="area">Parsed area.</param>
/// <returns><c>true</c> if parsing was a success, <c>false</c> otherwise.</returns>
[PublicAPI]
public static bool TryParseA1(string text, out ReferenceArea area)
{
if (text is null)
throw new ArgumentNullException();
Expand All @@ -141,9 +145,33 @@ public static ReferenceArea ParseA1(string text)
_ => false,
};
if (!isValid)
{
area = default;
return false;
}

area = TokenParser.ParseReference(text.AsSpan(), isA1: true);
return true;
}

/// <summary>
/// Parses area reference in A1 form. The possibilities are
/// <list type="bullet">
/// <item>Cell (e.g. <c>F8</c>).</item>
/// <item>Area (e.g. <c>B2:$D7</c>).</item>
/// <item>Colspan (e.g. <c>$D:$G</c>).</item>
/// <item>Rowspan (e.g. <c>14:$15</c>).</item>
/// </list>
/// Doesn't allow any whitespaces or extra values inside.
/// </summary>
/// <exception cref="ParsingException">Invalid input.</exception>
[PublicAPI]
public static ReferenceArea ParseA1(string text)
{
if (!TryParseA1(text, out var area))
throw new ParsingException($"Unable to parse '{text}'.");

return TokenParser.ParseReference(text.AsSpan(), isA1: true);
return area;
}

/// <summary>
Expand Down

0 comments on commit e812c0e

Please sign in to comment.