mirror of
https://gitee.com/dotnetchina/MiniExcel.git
synced 2024-11-30 02:47:39 +08:00
ADD : drafts\【MiniExcel】Reader Mode.linq , 【Reader】Basic Reader.linq ,【SqlConnection】Trace Reader Mode.linq
This commit is contained in:
parent
66ba1fa1f9
commit
d047d8402e
@ -1,145 +0,0 @@
|
||||
<Query Kind="Program">
|
||||
<NuGetReference>AngleSharp</NuGetReference>
|
||||
<NuGetReference>Dapper</NuGetReference>
|
||||
<NuGetReference>DocumentFormat.OpenXml</NuGetReference>
|
||||
<NuGetReference>Newtonsoft.Json</NuGetReference>
|
||||
<NuGetReference>System.Data.SqlClient</NuGetReference>
|
||||
<Namespace>Dapper</Namespace>
|
||||
<Namespace>Newtonsoft.Json</Namespace>
|
||||
<Namespace>System.Data.SqlClient</Namespace>
|
||||
<Namespace>System.IO.Compression</Namespace>
|
||||
<Namespace>System.Net.Http</Namespace>
|
||||
<Namespace>System.Threading.Tasks</Namespace>
|
||||
</Query>
|
||||
|
||||
void Main()
|
||||
{
|
||||
var source = new Dictionary<int, Dictionary<int, object>>()
|
||||
{
|
||||
{0,new Dictionary<int,object>(){{0,0},{3,3}}},
|
||||
{3,new Dictionary<int,object>(){{2,2}}},
|
||||
};
|
||||
Console.WriteLine(JsonConvert.SerializeObject(source, Newtonsoft.Json.Formatting.Indented));
|
||||
var rows = GetRows(@"D:\git\MiniExcel\samples\xlsx\TestCenterEmptyRow\TestCenterEmptyRow.xlsx").ToList();
|
||||
Console.WriteLine(rows);
|
||||
}
|
||||
|
||||
private static string ConvertToString(ZipArchiveEntry entry)
|
||||
{
|
||||
if (entry == null)
|
||||
return null;
|
||||
using (var eStream = entry.Open())
|
||||
using (var reader = new StreamReader(eStream))
|
||||
return reader.ReadToEnd();
|
||||
}
|
||||
|
||||
internal static class ExcelXName
|
||||
{
|
||||
internal readonly static XNamespace ExcelNamespace = XNamespace.Get("http://schemas.openxmlformats.org/spreadsheetml/2006/main");
|
||||
internal readonly static XNamespace ExcelRelationshipsNamepace = XNamespace.Get("http://schemas.openxmlformats.org/officeDocument/2006/relationships");
|
||||
internal readonly static XName Row;
|
||||
internal readonly static XName R;
|
||||
internal readonly static XName V;
|
||||
internal readonly static XName T;
|
||||
internal readonly static XName C;
|
||||
internal readonly static XName Dimension;
|
||||
static ExcelXName()
|
||||
{
|
||||
Row = XNamespace.Get("http://schemas.openxmlformats.org/spreadsheetml/2006/main") + "row";
|
||||
R = XNamespace.Get("http://schemas.openxmlformats.org/spreadsheetml/2006/main") + "r";
|
||||
V = XNamespace.Get("http://schemas.openxmlformats.org/spreadsheetml/2006/main") + "v";
|
||||
T = XNamespace.Get("http://schemas.openxmlformats.org/spreadsheetml/2006/main") + "t";
|
||||
C = XNamespace.Get("http://schemas.openxmlformats.org/spreadsheetml/2006/main") + "c";
|
||||
Dimension = XNamespace.Get("http://schemas.openxmlformats.org/spreadsheetml/2006/main") + "dimension";
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerable<IEnumerable<object>> GetRows(string path)
|
||||
{
|
||||
using (FileStream stream = new FileStream(path, FileMode.Open))
|
||||
using (ZipArchive archive = new ZipArchive(stream, ZipArchiveMode.Read, false, UTF8Encoding.UTF8))
|
||||
{
|
||||
var firstSheetEntry = archive.Entries.First(w => w.FullName.StartsWith("xl/worksheets/", StringComparison.OrdinalIgnoreCase));
|
||||
var xml = ConvertToString(firstSheetEntry);
|
||||
var xl = XElement.Parse(xml);
|
||||
|
||||
var maxRowIndex = 3;
|
||||
var maxColumnIndex = 3;
|
||||
|
||||
// first get sheet row count & column count
|
||||
|
||||
var rowIndex = 0;
|
||||
foreach (var row in xl.Descendants(ExcelXName.Row))
|
||||
{
|
||||
{
|
||||
var r = row.Attribute("r")?.Value?.ToString();
|
||||
|
||||
var rIndex = int.MinValue;
|
||||
if (int.TryParse(r, out var _rowIndex))
|
||||
rIndex = _rowIndex - 1; // The row attribute is 1 - based
|
||||
}
|
||||
|
||||
|
||||
var cells = new List<object>(maxColumnIndex);
|
||||
|
||||
foreach (var cell in row.Descendants(ExcelXName.C))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
yield return cells;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Main2()
|
||||
{
|
||||
{
|
||||
var dic = new Dictionary<int, Dictionary<int, object>>() {
|
||||
{0,new Dictionary<int,object>(){{0,0},{3,3}}},
|
||||
{3,new Dictionary<int,object>(){{2,3}}},
|
||||
};
|
||||
Console.WriteLine(JsonConvert.SerializeObject(dic, Newtonsoft.Json.Formatting.Indented));
|
||||
|
||||
var maxRowIndex = 3;
|
||||
var maxColumnIndex = 3;
|
||||
for (int rowIndex = 0; rowIndex <= maxRowIndex; rowIndex++)
|
||||
{
|
||||
if (!dic.ContainsKey(rowIndex))
|
||||
{
|
||||
var d = new Dictionary<int, object>();
|
||||
for (int columnIndex = 0; columnIndex <= maxColumnIndex; columnIndex++)
|
||||
{
|
||||
d.Add(columnIndex, null);
|
||||
}
|
||||
dic.Add(rowIndex, d);
|
||||
}
|
||||
else
|
||||
{
|
||||
var d = dic[rowIndex];
|
||||
for (int columnIndex = 0; columnIndex <= maxColumnIndex; columnIndex++)
|
||||
{
|
||||
if (!d.ContainsKey(columnIndex))
|
||||
{
|
||||
d.Add(columnIndex, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine(JsonConvert.SerializeObject(dic, Newtonsoft.Json.Formatting.Indented));
|
||||
}
|
||||
{
|
||||
var dic = new Dictionary<int, Dictionary<int, object>>() {
|
||||
{0,new Dictionary<int,object>(){{0,0},{1,null},{2,null},{3,3}}},
|
||||
{1,new Dictionary<int,object>(){{0,null},{1,null},{2,null},{3,null}}},
|
||||
{2,new Dictionary<int,object>(){{0,null},{1,null},{2,null},{3,null}}},
|
||||
{3,new Dictionary<int,object>(){{0,null},{1,null},{2,2},{3,null}}},
|
||||
};
|
||||
//Console.WriteLine(dic);
|
||||
var json = JsonConvert.SerializeObject(dic, Newtonsoft.Json.Formatting.Indented);
|
||||
Console.WriteLine(json);
|
||||
}
|
||||
}
|
||||
|
||||
// You can define other methods, fields, classes and namespaces here
|
350
drafts/【MiniExcel】Reader Mode.linq
Normal file
350
drafts/【MiniExcel】Reader Mode.linq
Normal file
@ -0,0 +1,350 @@
|
||||
<Query Kind="Program">
|
||||
<NuGetReference>AngleSharp</NuGetReference>
|
||||
<NuGetReference>Dapper</NuGetReference>
|
||||
<NuGetReference>DocumentFormat.OpenXml</NuGetReference>
|
||||
<NuGetReference>Newtonsoft.Json</NuGetReference>
|
||||
<NuGetReference>System.Data.SqlClient</NuGetReference>
|
||||
<Namespace>Dapper</Namespace>
|
||||
<Namespace>Newtonsoft.Json</Namespace>
|
||||
<Namespace>System.Data.SqlClient</Namespace>
|
||||
<Namespace>System.Net.Http</Namespace>
|
||||
<Namespace>System.Threading.Tasks</Namespace>
|
||||
<Namespace>System.IO.Compression</Namespace>
|
||||
</Query>
|
||||
|
||||
void Main()
|
||||
{
|
||||
using (var reader = new XlsxEasyRowsValueReader(@"D:\git\MiniExcel\samples\xlsx\TestCenterEmptyRow\TestCenterEmptyRow.xlsx"))
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
Console.WriteLine($"row : {reader.CurrentRowIndex}");
|
||||
Console.Write("Cells : | ");
|
||||
for (int i = 0; i < reader.FieldCount; i++)
|
||||
{
|
||||
var v = reader.GetValue(i);
|
||||
Console.Write(v == null ? null : v);
|
||||
Console.Write(" | ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class Worksheet
|
||||
{
|
||||
public int RowCount { get; set; }
|
||||
public int FieldCount { get; set; }
|
||||
public Dictionary<int, Dictionary<int, object>> Rows { get; set; }
|
||||
}
|
||||
|
||||
// You can define other methods, fields, classes and namespaces here
|
||||
public class MiniExcel
|
||||
{
|
||||
internal static Worksheet ConvertAsSheet(string path)
|
||||
{
|
||||
using (FileStream stream = new FileStream(path, FileMode.Open))
|
||||
using (ZipArchive archive = new ZipArchive(stream, ZipArchiveMode.Read, false, UTF8Encoding.UTF8))
|
||||
{
|
||||
//sharedStrings must in memory cache
|
||||
Dictionary<int, string> GetSharedStrings()
|
||||
{
|
||||
var sharedStringsEntry = archive.Entries.SingleOrDefault(w => w.FullName == "xl/sharedStrings.xml");
|
||||
var xml = ConvertToString(sharedStringsEntry);
|
||||
var xl = XElement.Parse(xml);
|
||||
var ts = xl.Descendants(ExcelXName.T).Select((s, i) => new { i, v = s.Value?.ToString() })
|
||||
.ToDictionary(s => s.i, s => s.v)
|
||||
;
|
||||
return ts;
|
||||
}
|
||||
|
||||
var sharedStrings = GetSharedStrings();
|
||||
|
||||
//notice: for performance just read first one and no care the order
|
||||
var rowIndexMaximum = int.MinValue;
|
||||
var columnIndexMaximum = int.MinValue;
|
||||
|
||||
|
||||
|
||||
var datarows = new Dictionary<int, Dictionary<int, object>>();
|
||||
var firstSheetEntry = archive.Entries.First(w => w.FullName.StartsWith("xl/worksheets/", StringComparison.OrdinalIgnoreCase));
|
||||
{
|
||||
var xml = ConvertToString(firstSheetEntry);
|
||||
var xl = XElement.Parse(xml);
|
||||
|
||||
foreach (var row in xl.Descendants(ExcelXName.Row))
|
||||
{
|
||||
//
|
||||
var datarow = new Dictionary<int, object>();
|
||||
{
|
||||
var r = row.Attribute("r")?.Value?.ToString();
|
||||
|
||||
var rowIndex = int.MinValue;
|
||||
if (int.TryParse(r, out var _rowIndex))
|
||||
rowIndex = _rowIndex - 1; // The row attribute is 1 - based
|
||||
rowIndexMaximum = Math.Max(rowIndexMaximum, rowIndex);
|
||||
|
||||
datarows.Add(rowIndex, datarow);
|
||||
}
|
||||
|
||||
foreach (var cell in row.Descendants(ExcelXName.C))
|
||||
{
|
||||
var t = cell.Attribute("t")?.Value?.ToString();
|
||||
var v = cell.Descendants(ExcelXName.V).SingleOrDefault()?.Value;
|
||||
if (t == "s")
|
||||
{
|
||||
if (!string.IsNullOrEmpty(v))
|
||||
v = sharedStrings[int.Parse(v)];
|
||||
}
|
||||
|
||||
var r = cell.Attribute("r")?.Value?.ToString();
|
||||
{
|
||||
var cellIndex = GetColumnIndex(r) - 1;
|
||||
columnIndexMaximum = Math.Max(columnIndexMaximum, cellIndex);
|
||||
|
||||
datarow.Add(cellIndex, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new Worksheet { FieldCount=columnIndexMaximum+1,RowCount=rowIndexMaximum+1,Rows=datarows};
|
||||
}
|
||||
}
|
||||
|
||||
private static string ConvertToString(ZipArchiveEntry entry)
|
||||
{
|
||||
if (entry == null)
|
||||
return null;
|
||||
using (var eStream = entry.Open())
|
||||
using (var reader = new StreamReader(eStream))
|
||||
return reader.ReadToEnd();
|
||||
}
|
||||
|
||||
/// <summary>X=CellLetter,Y=CellNumber,ex:A1=(1,1),B2=(2,2)</summary>
|
||||
internal static void ConvertCellToXY(string cell,out int x,out int y)
|
||||
{
|
||||
x=GetColumnIndex(cell);
|
||||
y=GetCellNumber(cell);
|
||||
}
|
||||
|
||||
internal static int GetColumnIndex(string cell)
|
||||
{
|
||||
const string keys = " ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
const int mode = 26;
|
||||
|
||||
var x = 0;
|
||||
var cellLetter = GetCellLetter(cell);
|
||||
//AA=27,ZZ=702
|
||||
for (int i = 0; i < cellLetter.Length; i++)
|
||||
x = x * mode + keys.IndexOf(cellLetter[i]);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
internal static int GetCellNumber(string cell)
|
||||
{
|
||||
if (string.IsNullOrEmpty(cell))
|
||||
throw new Exception("cell is null or empty");
|
||||
string cellNumber = string.Empty;
|
||||
for (int i = 0; i < cell.Length; i++)
|
||||
{
|
||||
if (Char.IsDigit(cell[i]))
|
||||
cellNumber += cell[i];
|
||||
}
|
||||
return int.Parse(cellNumber);
|
||||
}
|
||||
|
||||
internal static string GetCellLetter(string cell)
|
||||
{
|
||||
string GetCellLetter = string.Empty;
|
||||
for (int i = 0; i < cell.Length; i++)
|
||||
{
|
||||
if (Char.IsLetter(cell[i]))
|
||||
GetCellLetter += cell[i];
|
||||
}
|
||||
return GetCellLetter;
|
||||
}
|
||||
}
|
||||
|
||||
internal static class ExcelXName
|
||||
{
|
||||
internal readonly static XNamespace ExcelNamespace = XNamespace.Get("http://schemas.openxmlformats.org/spreadsheetml/2006/main");
|
||||
internal readonly static XNamespace ExcelRelationshipsNamepace = XNamespace.Get("http://schemas.openxmlformats.org/officeDocument/2006/relationships");
|
||||
internal readonly static XName Row;
|
||||
internal readonly static XName R;
|
||||
internal readonly static XName V;
|
||||
internal readonly static XName T;
|
||||
internal readonly static XName C;
|
||||
internal readonly static XName Dimension;
|
||||
static ExcelXName()
|
||||
{
|
||||
Row = XNamespace.Get("http://schemas.openxmlformats.org/spreadsheetml/2006/main") + "row";
|
||||
R = XNamespace.Get("http://schemas.openxmlformats.org/spreadsheetml/2006/main") + "r";
|
||||
V = XNamespace.Get("http://schemas.openxmlformats.org/spreadsheetml/2006/main") + "v";
|
||||
T = XNamespace.Get("http://schemas.openxmlformats.org/spreadsheetml/2006/main") + "t";
|
||||
C = XNamespace.Get("http://schemas.openxmlformats.org/spreadsheetml/2006/main") + "c";
|
||||
Dimension = XNamespace.Get("http://schemas.openxmlformats.org/spreadsheetml/2006/main") + "dimension";
|
||||
}
|
||||
}
|
||||
|
||||
public class XlsxEasyRowsValueReader : IDataReader
|
||||
{
|
||||
private static Worksheet[] _Sheets = new Worksheet[1];
|
||||
private Dictionary<int, Dictionary<int, object>> _Rows {get{return _Sheets[0].Rows;}}
|
||||
|
||||
public XlsxEasyRowsValueReader(string filePath)
|
||||
{
|
||||
_Sheets[0] = MiniExcel.ConvertAsSheet(filePath);
|
||||
}
|
||||
|
||||
public int RowCount {get{return _Sheets[0].RowCount;}}
|
||||
public int FieldCount {get{return _Sheets[0].FieldCount;}}
|
||||
public int Depth { get; private set; }
|
||||
public int CurrentRowIndex { get { return Depth - 1; } }
|
||||
|
||||
public object this[int i] => GetValue(i);
|
||||
public object this[string name] => GetValue(GetOrdinal(name));
|
||||
|
||||
public bool Read()
|
||||
{
|
||||
if (Depth == RowCount)
|
||||
return false;
|
||||
Depth++;
|
||||
return true;
|
||||
}
|
||||
|
||||
public string GetName(int i) => Helper.ConvertColumnName(i + 1);
|
||||
|
||||
|
||||
public int GetOrdinal(string name)
|
||||
{
|
||||
//TODO
|
||||
var keys = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray().ToList();
|
||||
var dic = keys.ToDictionary(s => s, s => keys.IndexOf(s));
|
||||
return dic[(name[0])];
|
||||
}
|
||||
|
||||
public object GetValue(int i)
|
||||
{
|
||||
//if (CurrentRowIndex < 0)
|
||||
// throw new InvalidOperationException("Invalid attempt to read when no data is present.");
|
||||
if (!_Rows.Keys.Contains(CurrentRowIndex))
|
||||
return null;
|
||||
if (_Rows[this.CurrentRowIndex].TryGetValue(i, out var v))
|
||||
return v;
|
||||
return null;
|
||||
}
|
||||
|
||||
public int GetValues(object[] values)
|
||||
{
|
||||
return this.Depth;
|
||||
}
|
||||
|
||||
//TODO: multiple sheets
|
||||
public bool NextResult() => false;
|
||||
|
||||
public void Dispose() { }
|
||||
|
||||
public void Close() { }
|
||||
|
||||
public int RecordsAffected => throw new NotImplementedException();
|
||||
|
||||
bool IDataReader.IsClosed => this.RowCount - 1 == this.Depth;
|
||||
|
||||
public string GetString(int i) => (string)GetValue(i);
|
||||
|
||||
public bool GetBoolean(int i) => (bool)GetValue(i);
|
||||
|
||||
public byte GetByte(int i) => (byte)GetValue(i);
|
||||
|
||||
public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length) => throw new NotImplementedException();
|
||||
|
||||
public char GetChar(int i) => (char)GetValue(i);
|
||||
|
||||
public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length) => throw new NotImplementedException();
|
||||
|
||||
public IDataReader GetData(int i) => throw new NotImplementedException();
|
||||
|
||||
public string GetDataTypeName(int i) => throw new NotImplementedException();
|
||||
|
||||
public DateTime GetDateTime(int i) => (DateTime)GetValue(i);
|
||||
|
||||
public decimal GetDecimal(int i) => (decimal)GetValue(i);
|
||||
|
||||
public double GetDouble(int i) => (double)GetValue(i);
|
||||
|
||||
public Type GetFieldType(int i)
|
||||
{
|
||||
var v = GetValue(i);
|
||||
return v == null ? typeof(string) : v.GetType();
|
||||
}
|
||||
|
||||
public float GetFloat(int i) => (float)GetValue(i);
|
||||
|
||||
public Guid GetGuid(int i) => (Guid)GetValue(i);
|
||||
|
||||
public short GetInt16(int i) => (short)GetValue(i);
|
||||
|
||||
public int GetInt32(int i) => (int)GetValue(i);
|
||||
|
||||
public long GetInt64(int i) => (long)GetValue(i);
|
||||
|
||||
public DataTable GetSchemaTable()
|
||||
{
|
||||
var dataTable = new DataTable("SchemaTable");
|
||||
dataTable.Locale = System.Globalization.CultureInfo.InvariantCulture;
|
||||
dataTable.Columns.Add("ColumnName", typeof(string));
|
||||
dataTable.Columns.Add("ColumnOrdinal", typeof(int));
|
||||
for (int i = 0; i < this.FieldCount; i++)
|
||||
{
|
||||
dataTable.Rows.Add(this.GetName(i), i);
|
||||
}
|
||||
DataColumnCollection columns = dataTable.Columns;
|
||||
foreach (DataColumn item in columns)
|
||||
{
|
||||
item.ReadOnly = true;
|
||||
}
|
||||
return dataTable;
|
||||
}
|
||||
|
||||
public bool IsDBNull(int i) => GetValue(i) == null;
|
||||
|
||||
}
|
||||
|
||||
internal static class Helper
|
||||
{
|
||||
public static TValue GetValueOrDefault<TKey, TValue>
|
||||
(this IDictionary<TKey, TValue> dictionary,
|
||||
TKey key,
|
||||
TValue defaultValue)
|
||||
{
|
||||
TValue value;
|
||||
return dictionary.TryGetValue(key, out value) ? value : defaultValue;
|
||||
}
|
||||
|
||||
public static TValue GetValueOrDefault<TKey, TValue>
|
||||
(this IDictionary<TKey, TValue> dictionary,
|
||||
TKey key,
|
||||
Func<TValue> defaultValueProvider)
|
||||
{
|
||||
TValue value;
|
||||
return dictionary.TryGetValue(key, out value) ? value
|
||||
: defaultValueProvider();
|
||||
}
|
||||
|
||||
internal static string ConvertColumnName(int x)
|
||||
{
|
||||
int dividend = x;
|
||||
string columnName = String.Empty;
|
||||
int modulo;
|
||||
|
||||
while (dividend > 0)
|
||||
{
|
||||
modulo = (dividend - 1) % 26;
|
||||
columnName = Convert.ToChar(65 + modulo).ToString() + columnName;
|
||||
dividend = (int)((dividend - modulo) / 26);
|
||||
}
|
||||
return columnName;
|
||||
}
|
||||
}
|
264
drafts/【Reader】Basic Reader.linq
Normal file
264
drafts/【Reader】Basic Reader.linq
Normal file
@ -0,0 +1,264 @@
|
||||
<Query Kind="Program">
|
||||
<NuGetReference>AngleSharp</NuGetReference>
|
||||
<NuGetReference>Dapper</NuGetReference>
|
||||
<NuGetReference>DocumentFormat.OpenXml</NuGetReference>
|
||||
<NuGetReference>Newtonsoft.Json</NuGetReference>
|
||||
<NuGetReference>System.Data.SqlClient</NuGetReference>
|
||||
<Namespace>Dapper</Namespace>
|
||||
<Namespace>Newtonsoft.Json</Namespace>
|
||||
<Namespace>System.Data.SqlClient</Namespace>
|
||||
<Namespace>System.Net.Http</Namespace>
|
||||
<Namespace>System.Threading.Tasks</Namespace>
|
||||
<Namespace>Xunit</Namespace>
|
||||
</Query>
|
||||
|
||||
#load "xunit"
|
||||
|
||||
#region private::Tests
|
||||
|
||||
[Fact]
|
||||
void Test_NullRow()
|
||||
{
|
||||
using (var reader = new XlsxEasyRowsValueReader(null))
|
||||
{
|
||||
Action testCode = () => { var v = reader[0]; };
|
||||
var ex = Record.Exception(testCode);
|
||||
Console.WriteLine();
|
||||
|
||||
Assert.NotNull(ex);
|
||||
Assert.IsType<InvalidOperationException>(ex);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
void Test_ReaderGetName()
|
||||
{
|
||||
using (var reader = new XlsxEasyRowsValueReader(null))
|
||||
{
|
||||
Assert.Equal("A", reader.GetName(0));
|
||||
Assert.Equal("B", reader.GetName(1));
|
||||
Assert.Equal("BD", reader.GetName(55));
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
void Test_ReaderGetOriginal()
|
||||
{
|
||||
using (var reader = new XlsxEasyRowsValueReader(null))
|
||||
{
|
||||
Assert.Equal(0, reader.GetOrdinal("A"));
|
||||
//Assert.Equal("B", reader.GetName(1));
|
||||
//Assert.Equal("BD", reader.GetName(55));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
void Main()
|
||||
{
|
||||
//RunTests(); // Call RunTests() or press Alt+Shift+T to initiate testing.
|
||||
|
||||
Console.WriteLine("========");
|
||||
using (var reader = new XlsxEasyRowsValueReader(null))
|
||||
{
|
||||
var st = reader.GetSchemaTable();
|
||||
Console.WriteLine(st);
|
||||
//todo
|
||||
var dt = new DataTable();
|
||||
dt.Load(reader);
|
||||
}
|
||||
|
||||
Console.WriteLine("========");
|
||||
using (var reader = new XlsxEasyRowsValueReader(null))
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
Console.WriteLine($"row : {reader.CurrentRowIndex}");
|
||||
Console.Write("Cells : | ");
|
||||
for (int i = 0; i < reader.FieldCount; i++)
|
||||
{
|
||||
var v = reader.GetValue(i);
|
||||
Console.Write(v == null ? null : v);
|
||||
Console.Write(" | ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine("========");
|
||||
using (var reader = new XlsxEasyRowsValueReader(null))
|
||||
{
|
||||
for (int i = 0; i < reader.FieldCount; i++)
|
||||
{
|
||||
var name = reader.GetName(i);
|
||||
Console.Write($" | name : {name}");
|
||||
//var ordinal = reader.GetOrdinal(name);
|
||||
//Console.Write($" | ordinal : {ordinal}");
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class XlsxEasyRowsValueReader : IDataReader
|
||||
{
|
||||
private static Dictionary<int, Dictionary<int, object>> _Rows { get; set; } = new Dictionary<int, Dictionary<int, object>>() {
|
||||
{0,new Dictionary<int,object>(){{0,0},{3,3}}},
|
||||
{3,new Dictionary<int,object>(){{2,2}}},
|
||||
};
|
||||
|
||||
public XlsxEasyRowsValueReader(string filePath)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public int RowCount { get; set; } = 4;
|
||||
public int FieldCount { get; set; } = 4;
|
||||
public int Depth { get; private set; }
|
||||
public int CurrentRowIndex { get { return Depth - 1; } }
|
||||
|
||||
public object this[int i] => GetValue(i);
|
||||
public object this[string name] => GetValue(GetOrdinal(name));
|
||||
|
||||
public bool Read()
|
||||
{
|
||||
if (Depth == RowCount)
|
||||
return false;
|
||||
Depth++;
|
||||
return true;
|
||||
}
|
||||
|
||||
public string GetName(int i) => Helper.ConvertColumnName(i + 1);
|
||||
|
||||
|
||||
public int GetOrdinal(string name)
|
||||
{
|
||||
//TODO
|
||||
var keys = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray().ToList();
|
||||
var dic = keys.ToDictionary(s => s, s => keys.IndexOf(s));
|
||||
return dic[(name[0])];
|
||||
}
|
||||
|
||||
public object GetValue(int i)
|
||||
{
|
||||
//if (CurrentRowIndex < 0)
|
||||
// throw new InvalidOperationException("Invalid attempt to read when no data is present.");
|
||||
if (!_Rows.Keys.Contains(CurrentRowIndex))
|
||||
return null;
|
||||
if (_Rows[this.CurrentRowIndex].TryGetValue(i, out var v))
|
||||
return v;
|
||||
return null;
|
||||
}
|
||||
|
||||
public int GetValues(object[] values) {
|
||||
return this.Depth;
|
||||
}
|
||||
|
||||
//TODO: multiple sheets
|
||||
public bool NextResult() => false;
|
||||
|
||||
public void Dispose() { }
|
||||
|
||||
public void Close() { }
|
||||
|
||||
public int RecordsAffected => throw new NotImplementedException();
|
||||
|
||||
bool IDataReader.IsClosed => this.RowCount - 1 == this.Depth;
|
||||
|
||||
public string GetString(int i) => (string)GetValue(i);
|
||||
|
||||
public bool GetBoolean(int i) => (bool)GetValue(i);
|
||||
|
||||
public byte GetByte(int i) => (byte)GetValue(i);
|
||||
|
||||
public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length) => throw new NotImplementedException();
|
||||
|
||||
public char GetChar(int i) => (char)GetValue(i);
|
||||
|
||||
public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length) => throw new NotImplementedException();
|
||||
|
||||
public IDataReader GetData(int i) => throw new NotImplementedException();
|
||||
|
||||
public string GetDataTypeName(int i) => throw new NotImplementedException();
|
||||
|
||||
public DateTime GetDateTime(int i) => (DateTime)GetValue(i);
|
||||
|
||||
public decimal GetDecimal(int i) => (decimal)GetValue(i);
|
||||
|
||||
public double GetDouble(int i) => (double)GetValue(i);
|
||||
|
||||
public Type GetFieldType(int i)
|
||||
{
|
||||
var v = GetValue(i);
|
||||
return v==null ? typeof(string) : v.GetType();
|
||||
}
|
||||
|
||||
public float GetFloat(int i) => (float)GetValue(i);
|
||||
|
||||
public Guid GetGuid(int i) => (Guid)GetValue(i);
|
||||
|
||||
public short GetInt16(int i) => (short)GetValue(i);
|
||||
|
||||
public int GetInt32(int i) => (int)GetValue(i);
|
||||
|
||||
public long GetInt64(int i) => (long)GetValue(i);
|
||||
|
||||
public DataTable GetSchemaTable()
|
||||
{
|
||||
var dataTable = new DataTable("SchemaTable");
|
||||
dataTable.Locale = System.Globalization.CultureInfo.InvariantCulture;
|
||||
dataTable.Columns.Add("ColumnName", typeof(string));
|
||||
dataTable.Columns.Add("ColumnOrdinal", typeof(int));
|
||||
for (int i = 0; i < this.FieldCount; i++)
|
||||
{
|
||||
dataTable.Rows.Add(this.GetName(i), i);
|
||||
}
|
||||
DataColumnCollection columns = dataTable.Columns;
|
||||
foreach (DataColumn item in columns)
|
||||
{
|
||||
item.ReadOnly = true;
|
||||
}
|
||||
return dataTable;
|
||||
}
|
||||
|
||||
public bool IsDBNull(int i) => GetValue(i) == null;
|
||||
|
||||
}
|
||||
|
||||
internal static class Helper
|
||||
{
|
||||
public static TValue GetValueOrDefault<TKey, TValue>
|
||||
(this IDictionary<TKey, TValue> dictionary,
|
||||
TKey key,
|
||||
TValue defaultValue)
|
||||
{
|
||||
TValue value;
|
||||
return dictionary.TryGetValue(key, out value) ? value : defaultValue;
|
||||
}
|
||||
|
||||
public static TValue GetValueOrDefault<TKey, TValue>
|
||||
(this IDictionary<TKey, TValue> dictionary,
|
||||
TKey key,
|
||||
Func<TValue> defaultValueProvider)
|
||||
{
|
||||
TValue value;
|
||||
return dictionary.TryGetValue(key, out value) ? value
|
||||
: defaultValueProvider();
|
||||
}
|
||||
|
||||
internal static string ConvertColumnName(int x)
|
||||
{
|
||||
int dividend = x;
|
||||
string columnName = String.Empty;
|
||||
int modulo;
|
||||
|
||||
while (dividend > 0)
|
||||
{
|
||||
modulo = (dividend - 1) % 26;
|
||||
columnName = Convert.ToChar(65 + modulo).ToString() + columnName;
|
||||
dividend = (int)((dividend - modulo) / 26);
|
||||
}
|
||||
return columnName;
|
||||
}
|
||||
}
|
39
drafts/【SqlConnection】Trace Reader Mode.linq
Normal file
39
drafts/【SqlConnection】Trace Reader Mode.linq
Normal file
@ -0,0 +1,39 @@
|
||||
<Query Kind="Program">
|
||||
<Connection>
|
||||
<ID>2a2e3c0b-0e23-4992-bf19-66db2739e377</ID>
|
||||
<Persist>true</Persist>
|
||||
<Server>(localdb)\mssqllocaldb</Server>
|
||||
<Database>Northwind</Database>
|
||||
</Connection>
|
||||
<NuGetReference>AngleSharp</NuGetReference>
|
||||
<NuGetReference>Dapper</NuGetReference>
|
||||
<NuGetReference>DocumentFormat.OpenXml</NuGetReference>
|
||||
<NuGetReference>Newtonsoft.Json</NuGetReference>
|
||||
<NuGetReference>System.Data.SqlClient</NuGetReference>
|
||||
<Namespace>Dapper</Namespace>
|
||||
<Namespace>Newtonsoft.Json</Namespace>
|
||||
<Namespace>System.Data.SqlClient</Namespace>
|
||||
<Namespace>System.Net.Http</Namespace>
|
||||
<Namespace>System.Threading.Tasks</Namespace>
|
||||
</Query>
|
||||
|
||||
void Main()
|
||||
{
|
||||
using (var cn = (SqlConnection)this.Connection)
|
||||
{
|
||||
cn.Open();
|
||||
using(var cmd = cn.CreateCommand()){
|
||||
cmd.CommandText="select 1 id";
|
||||
using(var reader = cmd.ExecuteReader()){
|
||||
var name = reader.GetName(0);
|
||||
Console.WriteLine(name);
|
||||
var dt = reader.GetSchemaTable();
|
||||
Console.WriteLine(dt);
|
||||
var v = reader.GetValue(0);
|
||||
var vs = reader.GetValues(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// You can define other methods, fields, classes and namespaces here
|
Loading…
Reference in New Issue
Block a user