Skip to content
Merged
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
34 changes: 29 additions & 5 deletions src/ExcelDataReader.Tests/ExcelBinaryReaderTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public void TestOpenOffice()
}

/// <summary>
/// Issue 11 - OpenOffice files were skipping the first row if IsFirstRowAsColumnNames = false;
/// Issue 11 - OpenOffice files were skipping the first row if IsFirstRowAsColumnNames = false.
/// </summary>
[Test]
public void GitIssue11OpenOfficeRowCount()
Expand Down Expand Up @@ -170,7 +170,7 @@ public void Issue11572CodePage()
}

/// <summary>
/// Not fixed yet
/// Not fixed yet.
/// </summary>
[Test]
public void Issue11545NoIndex()
Expand Down Expand Up @@ -211,7 +211,7 @@ public void Issue11636BiffStream()
/// Not fixed yet
/// The problem occurs with unseekable stream and logic related to minifat that uses seek
/// It should probably only use seek if it needs to go backwards, I think at the moment it uses seek all the time
/// which is probably not good for performance
/// which is probably not good for performance.
/// </summary>
[Test]
[Ignore("Not fixed yet")]
Expand All @@ -228,7 +228,7 @@ public void Issue1163911644ForwardOnlyStream()
/// Not fixed yet
/// The problem occurs with unseekable stream and logic related to minifat that uses seek
/// It should probably only use seek if it needs to go backwards, I think at the moment it uses seek all the time
/// which is probably not good for performance
/// which is probably not good for performance.
/// </summary>
[Test]
public void Issue12556Corrupt()
Expand All @@ -243,7 +243,7 @@ public void Issue12556Corrupt()
}

/// <summary>
/// Some spreadsheets were crashing with index out of range error (from SSRS)
/// Some spreadsheets were crashing with index out of range error (from SSRS).
/// </summary>
[Test]
public void TestIssue11818OutOfRange()
Expand Down Expand Up @@ -1069,6 +1069,30 @@ public void GitIssue578()
Assert.That(values3, Is.EqualTo(new object[] { 1, 2, 3, 4 }));
}

[Test]
public void GitIssue642_ActiveSheet()
{
using var reader = OpenReader("Test_git_issue_642");
var dataSet = reader.AsDataSet(new ExcelDataSetConfiguration()
{
FilterSheet = (tableReader, sheetIndex) => tableReader.IsActiveSheet
});
Assert.That(reader.ActiveSheet, Is.EqualTo(5));
Assert.That(dataSet.Tables[0].TableName, Is.EqualTo("List6"));
}

[Test]
public void GitIssue642_ActiveSheet_SingleWorksheet()
{
using var reader = OpenReader("Test_git_issue_642onesheet");
var dataSet = reader.AsDataSet(new ExcelDataSetConfiguration()
{
FilterSheet = (tableReader, sheetIndex) => tableReader.IsActiveSheet
});
Assert.That(reader.ActiveSheet, Is.EqualTo(0));
Assert.That(dataSet.Tables[0].TableName, Is.EqualTo("List1"));
}

protected override IExcelDataReader OpenReader(Stream stream, ExcelReaderConfiguration configuration = null)
{
return ExcelReaderFactory.CreateBinaryReader(stream, configuration);
Expand Down
14 changes: 13 additions & 1 deletion src/ExcelDataReader.Tests/ExcelCsvReaderTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace ExcelDataReader.Tests;

/// <summary>
/// Most CSV test data came from csv-spectrum: https://github.com/maxogden/csv-spectrum
/// Most CSV test data came from csv-spectrum: https://github.com/maxogden/csv-spectrum.
/// </summary>
public class ExcelCsvReaderTest
{
Expand Down Expand Up @@ -467,4 +467,16 @@ public void GitIssue463()
Assert.That(row4, Is.EqualTo(new object[] { "Test3", "IJK", "ZZ", "10,143.27", "0.00" }));
});
}

[Test]
public void GitIssue642_ActiveSheet()
{
using var reader = ExcelReaderFactory.CreateCsvReader(Configuration.GetTestWorkbook("csv\\MOCK_DATA.csv"));
var dataSet = reader.AsDataSet(new ExcelDataSetConfiguration()
{
FilterSheet = (tableReader, sheetIndex) => tableReader.IsActiveSheet
});
Assert.That(reader.ActiveSheet, Is.EqualTo(0));
Assert.That(dataSet.Tables.Count, Is.EqualTo(1));
}
}
24 changes: 24 additions & 0 deletions src/ExcelDataReader.Tests/ExcelOpenXmlBinaryReaderTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,30 @@ public void GitIssue635()
Assert.That(dataSet.Tables[0].Rows[0].ItemArray, Is.EqualTo(new[] { "A", "B", "C", "D", "E", "F" }));
}

[Test]
public void GitIssue642_ActiveSheet()
{
using var reader = OpenReader("Test_git_issue_642");
var dataSet = reader.AsDataSet(new ExcelDataSetConfiguration()
{
FilterSheet = (tableReader, sheetIndex) => tableReader.IsActiveSheet
});
Assert.That(reader.ActiveSheet, Is.EqualTo(5));
Assert.That(dataSet.Tables[0].TableName, Is.EqualTo("List6"));
}

[Test]
public void GitIssue642_ActiveSheet_SingleWorksheet()
{
using var reader = OpenReader("Test_git_issue_642onesheet");
var dataSet = reader.AsDataSet(new ExcelDataSetConfiguration()
{
FilterSheet = (tableReader, sheetIndex) => tableReader.IsActiveSheet
});
Assert.That(reader.ActiveSheet, Is.EqualTo(0));
Assert.That(dataSet.Tables[0].TableName, Is.EqualTo("List1"));
}

/// <inheritdoc />
protected override Stream OpenStream(string name)
{
Expand Down
24 changes: 24 additions & 0 deletions src/ExcelDataReader.Tests/ExcelOpenXmlReaderTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,30 @@ public void GitIssue518MultipleHeaderRows()
}
}

[Test]
public void GitIssue642_ActiveSheet()
{
using var reader = OpenReader("Test_git_issue_642");
var dataSet = reader.AsDataSet(new ExcelDataSetConfiguration()
{
FilterSheet = (tableReader, sheetIndex) => tableReader.IsActiveSheet
});
Assert.That(reader.ActiveSheet, Is.EqualTo(5));
Assert.That(dataSet.Tables[0].TableName, Is.EqualTo("List6"));
}

[Test]
public void GitIssue642_ActiveSheet_SingleWorksheet()
{
using var reader = OpenReader("Test_git_issue_642onesheet");
var dataSet = reader.AsDataSet(new ExcelDataSetConfiguration()
{
FilterSheet = (tableReader, sheetIndex) => tableReader.IsActiveSheet
});
Assert.That(reader.ActiveSheet, Is.EqualTo(0));
Assert.That(dataSet.Tables[0].TableName, Is.EqualTo("List1"));
}

protected override IExcelDataReader OpenReader(Stream stream, ExcelReaderConfiguration configuration = null)
=> ExcelReaderFactory.CreateOpenXmlReader(stream, configuration);

Expand Down
2 changes: 1 addition & 1 deletion src/ExcelDataReader.Tests/ExcelTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public void Issue11773ExponentialCommas()
}

/// <summary>
/// Makes sure that we can read data from the first row of last sheet
/// Makes sure that we can read data from the first row of last sheet.
/// </summary>
[Test]
public void Issue12271NextResultSet()
Expand Down
6 changes: 6 additions & 0 deletions src/ExcelDataReader/Core/BinaryFormat/XlsWorkbook.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ internal XlsWorkbook(Stream stream, string password, Encoding fallbackEncoding)

public int ResultsCount => Sheets?.Count ?? -1;

public int ActiveSheet { get; private set; }

public static bool IsRawBiffStream(byte[] bytes)
{
if (bytes.Length < 8)
Expand Down Expand Up @@ -203,6 +205,10 @@ private void ReadWorkbookGlobals(XlsBiffStream biffStream)
ExtSST = rec;
break;

case XlsBiffRecord _ when rec.Id == BIFFRECORDTYPE.WINDOW1:
ActiveSheet = rec.ReadInt16(10);
break;

// case BIFFRECORDTYPE.PROTECT:
// case BIFFRECORDTYPE.PROT4REVPASSWORD:
// IsProtected
Expand Down
5 changes: 5 additions & 0 deletions src/ExcelDataReader/Core/BinaryFormat/XlsWorksheet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ public XlsWorksheet(XlsWorkbook workbook, XlsBiffBoundSheet refSheet, Stream str
/// </summary>
public string VisibleState { get; }

/// <summary>
/// Gets a value indicating whether the sheet is active.
/// </summary>
public bool IsActiveSheet { get; }

public HeaderFooter HeaderFooter { get; private set; }

public CellRange[] MergeCells { get; private set; }
Expand Down
2 changes: 2 additions & 0 deletions src/ExcelDataReader/Core/CsvFormat/CsvWorkbook.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ internal sealed class CsvWorkbook(Stream stream, Encoding encoding, char[] autod
{
public int ResultsCount => 1;

public int ActiveSheet => 0;

public Stream Stream { get; } = stream;

public Encoding Encoding { get; } = encoding;
Expand Down
4 changes: 4 additions & 0 deletions src/ExcelDataReader/Core/CsvFormat/CsvWorksheet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ public CsvWorksheet(Stream stream, Encoding fallbackEncoding, char[] autodetectS
}
}

public static int ActiveSheet => 0;

public static bool IsActiveSheet => true;

public string Name => string.Empty;

public string CodeName => null;
Expand Down
2 changes: 2 additions & 0 deletions src/ExcelDataReader/Core/IWorkbook.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ internal interface IWorkbook<TWorksheet>
{
int ResultsCount { get; }

int ActiveSheet { get; }

IEnumerable<TWorksheet> ReadWorksheets();

NumberFormatString GetNumberFormatString(int index);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ internal sealed class BiffWorkbookReader(Stream stream, Dictionary<string, strin
{
private const int WorkbookPr = 0x99;
private const int Sheet = 0x9C;

private const int BrtBookView = 0x9e;

private readonly Dictionary<string, string> _worksheetRels = worksheetRels;

private enum SheetVisibility : byte
Expand Down Expand Up @@ -42,6 +43,11 @@ protected override Record ReadOverride(byte[] buffer, uint recordId, uint record
string name = GetString(buffer, offset + 4, nameLength);

return new SheetRecord(name, id, rid, state, rid != null && _worksheetRels.TryGetValue(rid, out var path) ? path : null);

case BrtBookView:
int activeSheet = (int)GetDWord(buffer, 24);
return new WorkbookActRecord(activeSheet);

default:
return Record.Default;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExcelDataReader.Core.OpenXmlFormat.Records;

internal sealed class WorkbookActRecord : Record
{
public WorkbookActRecord(int activeSheet)
{
this.ActiveSheet = activeSheet;
}

public int ActiveSheet { get; }
}
5 changes: 5 additions & 0 deletions src/ExcelDataReader/Core/OpenXmlFormat/XlsxWorkbook.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public XlsxWorkbook(ZipWorker zipWorker)

public int ResultsCount => Sheets?.Count ?? -1;

public int ActiveSheet { get; private set; }

public IEnumerable<XlsxWorksheet> ReadWorksheets()
{
foreach (var sheet in Sheets)
Expand All @@ -45,6 +47,9 @@ private void ReadWorkbook()
case SheetRecord sheet:
Sheets.Add(sheet);
break;
case WorkbookActRecord activeSheet:
ActiveSheet = activeSheet.ActiveSheet;
break;
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/ExcelDataReader/Core/OpenXmlFormat/XlsxWorksheet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ public XlsxWorksheet(ZipWorker document, XlsxWorkbook workbook, SheetRecord refS

public string VisibleState { get; }

public bool IsActiveSheet { get; }

public HeaderFooter HeaderFooter { get; }

public double DefaultRowHeight { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,28 @@ protected override IEnumerable<Record> ReadOverride()
}
}
}
else if (Reader.IsStartElement("bookViews", ProperNamespaces.NsSpreadsheetMl))
{
if (!XmlReaderHelper.ReadFirstContent(Reader))
{
continue;
}

while (!Reader.EOF)
{
if (Reader.IsStartElement("workbookView", ProperNamespaces.NsSpreadsheetMl))
{
string activeTab = Reader.GetAttribute("activeTab");
int activeTabInt = int.TryParse(activeTab, out var result) ? result : 0;
yield return new WorkbookActRecord(activeTabInt);
Reader.Skip();
}
else if (!XmlReaderHelper.SkipContent(Reader))
{
break;
}
}
}
else if (!XmlReaderHelper.SkipContent(Reader))
{
yield break;
Expand Down
12 changes: 11 additions & 1 deletion src/ExcelDataReader/ExcelDataReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ internal abstract class ExcelDataReader<TWorkbook, TWorksheet> : IExcelDataReade
private IEnumerator<Row> _rowIterator;
private IEnumerator<TWorksheet> _cachedWorksheetIterator;
private List<TWorksheet> _cachedWorksheets;
private int _idx;

~ExcelDataReader()
{
Expand All @@ -28,6 +29,10 @@ internal abstract class ExcelDataReader<TWorkbook, TWorksheet> : IExcelDataReade

public string VisibleState => _worksheetIterator?.Current?.VisibleState;

public int ActiveSheet => this.Workbook.ActiveSheet;

public bool IsActiveSheet => _idx == this.Workbook.ActiveSheet;

public HeaderFooter HeaderFooter => _worksheetIterator?.Current?.HeaderFooter;

// We shouldn't expose the internal array here.
Expand Down Expand Up @@ -213,11 +218,13 @@ public void Reset()
_worksheetIterator = null;
_rowIterator = null;

_idx = 0;

ResetSheetData();

if (Workbook != null)
{
_worksheetIterator = ReadWorksheetsWithCache().GetEnumerator(); // Workbook.ReadWorksheets().GetEnumerator();
_worksheetIterator = ReadWorksheetsWithCache().GetEnumerator();
if (!_worksheetIterator.MoveNext())
{
_worksheetIterator.Dispose();
Expand Down Expand Up @@ -263,6 +270,9 @@ public bool NextResult()
}

_rowIterator = _worksheetIterator.Current.ReadRows().GetEnumerator();

_idx++;

return true;
}

Expand Down
10 changes: 10 additions & 0 deletions src/ExcelDataReader/IExcelDataReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ public interface IExcelDataReader : IDataReader
/// </summary>
string VisibleState { get; }

/// <summary>
/// Gets the active sheet.
/// </summary>
int ActiveSheet { get; }

/// <summary>
/// Gets a value indicating whether the worksheet is active.
/// </summary>
bool IsActiveSheet { get; }

/// <summary>
/// Gets the sheet header and footer -or- <see langword="null"/> if none set.
/// </summary>
Expand Down
Binary file added src/TestData/Test_git_issue_642.xls
Binary file not shown.
Binary file added src/TestData/Test_git_issue_642.xlsb
Binary file not shown.
Binary file added src/TestData/Test_git_issue_642.xlsx
Binary file not shown.
Binary file added src/TestData/Test_git_issue_642onesheet.xls
Binary file not shown.
Binary file added src/TestData/Test_git_issue_642onesheet.xlsb
Binary file not shown.
Binary file added src/TestData/Test_git_issue_642onesheet.xlsx
Binary file not shown.