Last active
October 17, 2018 15:33
-
-
Save YuukanOO/45258d0cadc27d99337aa6fe51ce2d14 to your computer and use it in GitHub Desktop.
Ascii table parser in C#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
using (var package = new ExcelPackage(File.Create(@"C:\Temp\test.xlsx"))) | |
{ | |
var sheet = package.Workbook.Worksheets.Add("Sandbox"); | |
var parser = new TableParser(1, 1); | |
parser.InsertRow += (row) => sheet.InsertRow(row, 1); | |
parser.SetCell += (row, col, tag) => sheet.Cells[row, col].Value = tag; | |
parser.MergeCell += (fromRow, fromCol, toRow, toCol) => sheet.Cells[fromRow, fromCol, toRow, toCol].Merge = true; | |
parser.Parse(@" | |
|-------------------------------|---------------| | |
| 1 | 11 | | |
|---------------|---------------|---------------| | |
| 2 | 3 | 12 | | |
|---------------|---------------|---------------| | |
| 4 | 5 | 13 | | |
| |---------------| | | |
| | 6 | | | |
|---------------|---------------| | | |
| 7 | 8 | | | |
|---------------| | | | |
| 9 | | | | |
| |---------------| | | |
| | 10 | | | |
|---------------|---------------|---------------|"); | |
parser.Seek(parser.CurrentRow + 1, 1); | |
parser.Parse(@" | |
|------------------------------------------------------------------------------------| | |
| a | | | | |
| |----------------|----------------|----------------|----------------| | |
| | b | c | d | e | | |
|----------------|----------------|----------------|----------------|----------------| | |
"); | |
package.Save(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public sealed class TableParser | |
{ | |
class Range | |
{ | |
public int FromRow; | |
public int ToRow; | |
public int FromCol; | |
public int ToCol; | |
} | |
#region Delegates | |
public delegate void InsertRowDelegate(int row); | |
public delegate void SetCellDelegate(int row, int col, string section); | |
public delegate void MergeCellDelegate(int fromRow, int fromCol, int toRow, int toCol); | |
#endregion | |
#region Events | |
public event InsertRowDelegate InsertRow; | |
public event SetCellDelegate SetCell; | |
public event MergeCellDelegate MergeCell; | |
#endregion | |
public int CurrentRow { get; private set; } | |
private int _rowOffset; | |
private int _colOffset; | |
private Dictionary<int, Range> _cellsSpan; | |
private int[] _columnsDefinitions; | |
private readonly Regex _colDelimiterRegex = new Regex("([|])", RegexOptions.Compiled); | |
private readonly Regex _rowDelimiterRegex = new Regex("([-]+)", RegexOptions.Compiled); | |
private readonly Regex _rowContentRegex = new Regex("([^|]+)", RegexOptions.Compiled); | |
public TableParser(int rowOffset = 0, int colOffset = 0) | |
{ | |
_rowOffset = rowOffset; | |
_colOffset = colOffset; | |
} | |
public void Seek(int row, int col) | |
{ | |
_rowOffset = row; | |
_colOffset = col; | |
} | |
private int FindCol(int index) | |
{ | |
for (var idx = 0; idx <= _columnsDefinitions.Length; ++idx) | |
{ | |
if (index <= _columnsDefinitions[idx] || _columnsDefinitions[idx] >= index) | |
{ | |
return idx; | |
} | |
} | |
return 0; | |
} | |
public void Parse(string ascii) | |
{ | |
CurrentRow = 0; | |
_columnsDefinitions = new int[0]; | |
_cellsSpan = new Dictionary<int, Range>(); | |
var lines = ascii.Split(new string[] { "\n", "\r\n" }, StringSplitOptions.RemoveEmptyEntries); | |
foreach (var line in lines) | |
{ | |
var matches = _colDelimiterRegex.Matches(line); | |
if (matches.Count > _columnsDefinitions.Length) | |
{ | |
_columnsDefinitions = matches.Skip(1).Select(o => o.Index).ToArray(); | |
} | |
} | |
foreach (var line in lines) | |
{ | |
var matches = _rowDelimiterRegex.Matches(line); | |
if (matches.Any()) | |
{ | |
foreach (Match match in matches) | |
{ | |
var colToClose = FindCol(match.Index); | |
if (_cellsSpan.TryGetValue(colToClose, out Range range)) | |
{ | |
if (range.FromRow != range.ToRow || range.FromCol != range.ToCol) | |
{ | |
MergeCell?.Invoke( | |
_rowOffset + range.FromRow, | |
_colOffset + range.FromCol, | |
_rowOffset + range.ToRow, | |
_colOffset + range.ToCol); | |
} | |
_cellsSpan.Remove(colToClose); | |
} | |
} | |
continue; | |
} | |
InsertRow?.Invoke(_rowOffset + CurrentRow); | |
foreach (Match match in _rowContentRegex.Matches(line)) | |
{ | |
var curStartCol = FindCol(match.Index); | |
var curEndCol = FindCol(match.Index + match.Length); | |
if (!_cellsSpan.ContainsKey(curStartCol)) | |
{ | |
_cellsSpan[curStartCol] = new Range | |
{ | |
FromRow = CurrentRow, | |
FromCol = curStartCol, | |
ToCol = curEndCol, | |
}; | |
SetCell?.Invoke(_rowOffset + CurrentRow, _colOffset + curStartCol, match.Value.Trim()); | |
} | |
_cellsSpan[curStartCol].ToRow = CurrentRow; | |
} | |
++CurrentRow; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment