mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-18 00:34:28 +08:00
support setting whether the data table in csv / xls / xlsx files contains a header row
This commit is contained in:
@@ -13,7 +13,8 @@ import (
|
||||
|
||||
// CsvFileBasicDataTable defines the structure of csv data table
|
||||
type CsvFileBasicDataTable struct {
|
||||
allLines [][]string
|
||||
allLines [][]string
|
||||
hasTitleLine bool
|
||||
}
|
||||
|
||||
// CsvFileBasicDataTableRow defines the structure of csv data table row
|
||||
@@ -34,7 +35,11 @@ func (t *CsvFileBasicDataTable) DataRowCount() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
return len(t.allLines) - 1
|
||||
if t.hasTitleLine {
|
||||
return len(t.allLines) - 1
|
||||
} else {
|
||||
return len(t.allLines)
|
||||
}
|
||||
}
|
||||
|
||||
// HeaderColumnNames returns the header column name list
|
||||
@@ -43,14 +48,24 @@ func (t *CsvFileBasicDataTable) HeaderColumnNames() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
return t.allLines[0]
|
||||
if t.hasTitleLine {
|
||||
return t.allLines[0]
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// DataRowIterator returns the iterator of data row
|
||||
func (t *CsvFileBasicDataTable) DataRowIterator() datatable.BasicDataTableRowIterator {
|
||||
startIndex := -1
|
||||
|
||||
if t.hasTitleLine {
|
||||
startIndex = 0
|
||||
}
|
||||
|
||||
return &CsvFileBasicDataTableRowIterator{
|
||||
dataTable: t,
|
||||
currentIndex: 0,
|
||||
currentIndex: startIndex,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,18 +110,19 @@ func (t *CsvFileBasicDataTableRowIterator) Next() datatable.BasicDataTableRow {
|
||||
}
|
||||
|
||||
// CreateNewCsvBasicDataTable returns comma separated values data table by io readers
|
||||
func CreateNewCsvBasicDataTable(ctx core.Context, reader io.Reader) (datatable.BasicDataTable, error) {
|
||||
return createNewCsvFileBasicDataTable(ctx, reader, ',')
|
||||
func CreateNewCsvBasicDataTable(ctx core.Context, reader io.Reader, hasTitleLine bool) (datatable.BasicDataTable, error) {
|
||||
return createNewCsvFileBasicDataTable(ctx, reader, ',', hasTitleLine)
|
||||
}
|
||||
|
||||
// CreateNewCustomCsvBasicDataTable returns character separated values data table by io readers
|
||||
func CreateNewCustomCsvBasicDataTable(allLines [][]string) datatable.BasicDataTable {
|
||||
func CreateNewCustomCsvBasicDataTable(allLines [][]string, hasTitleLine bool) datatable.BasicDataTable {
|
||||
return &CsvFileBasicDataTable{
|
||||
allLines: allLines,
|
||||
allLines: allLines,
|
||||
hasTitleLine: hasTitleLine,
|
||||
}
|
||||
}
|
||||
|
||||
func createNewCsvFileBasicDataTable(ctx core.Context, reader io.Reader, separator rune) (*CsvFileBasicDataTable, error) {
|
||||
func createNewCsvFileBasicDataTable(ctx core.Context, reader io.Reader, separator rune, hasTitleLine bool) (*CsvFileBasicDataTable, error) {
|
||||
csvReader := csv.NewReader(reader)
|
||||
csvReader.Comma = separator
|
||||
csvReader.FieldsPerRecord = -1
|
||||
@@ -133,6 +149,7 @@ func createNewCsvFileBasicDataTable(ctx core.Context, reader io.Reader, separato
|
||||
}
|
||||
|
||||
return &CsvFileBasicDataTable{
|
||||
allLines: allLines,
|
||||
allLines: allLines,
|
||||
hasTitleLine: hasTitleLine,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -14,7 +14,17 @@ func TestCsvFileBasicDataTableDataRowCount(t *testing.T) {
|
||||
{"A1", "B1", "C1"},
|
||||
{"A2", "B2", "C2"},
|
||||
{"A3", "B3", "C3"},
|
||||
})
|
||||
}, false)
|
||||
|
||||
assert.Equal(t, 3, datatable.DataRowCount())
|
||||
}
|
||||
|
||||
func TestCsvFileBasicDataTableDataRowCount_HasTitleLine(t *testing.T) {
|
||||
datatable := CreateNewCustomCsvBasicDataTable([][]string{
|
||||
{"A1", "B1", "C1"},
|
||||
{"A2", "B2", "C2"},
|
||||
{"A3", "B3", "C3"},
|
||||
}, true)
|
||||
|
||||
assert.Equal(t, 2, datatable.DataRowCount())
|
||||
}
|
||||
@@ -22,14 +32,16 @@ func TestCsvFileBasicDataTableDataRowCount(t *testing.T) {
|
||||
func TestCsvFileBasicDataTableDataRowCount_OnlyHeaderLine(t *testing.T) {
|
||||
datatable := CreateNewCustomCsvBasicDataTable([][]string{
|
||||
{"A1", "B1", "C1"},
|
||||
})
|
||||
}, true)
|
||||
|
||||
assert.Equal(t, 0, datatable.DataRowCount())
|
||||
}
|
||||
|
||||
func TestCsvFileBasicDataTableDataRowCount_EmptyContent(t *testing.T) {
|
||||
datatable := CreateNewCustomCsvBasicDataTable([][]string{})
|
||||
datatable := CreateNewCustomCsvBasicDataTable([][]string{}, false)
|
||||
assert.Equal(t, 0, datatable.DataRowCount())
|
||||
|
||||
datatable = CreateNewCustomCsvBasicDataTable([][]string{}, true)
|
||||
assert.Equal(t, 0, datatable.DataRowCount())
|
||||
}
|
||||
|
||||
@@ -38,14 +50,16 @@ func TestCsvFileBasicDataTableHeaderColumnNames(t *testing.T) {
|
||||
{"A1", "B1", "C1"},
|
||||
{"A2", "B2", "C2"},
|
||||
{"A3", "B3", "C3"},
|
||||
})
|
||||
}, true)
|
||||
|
||||
assert.EqualValues(t, []string{"A1", "B1", "C1"}, datatable.HeaderColumnNames())
|
||||
}
|
||||
|
||||
func TestCsvFileBasicDataTableHeaderColumnNames_EmptyContent(t *testing.T) {
|
||||
datatable := CreateNewCustomCsvBasicDataTable([][]string{})
|
||||
datatable := CreateNewCustomCsvBasicDataTable([][]string{}, false)
|
||||
assert.Nil(t, datatable.HeaderColumnNames())
|
||||
|
||||
datatable = CreateNewCustomCsvBasicDataTable([][]string{}, true)
|
||||
assert.Nil(t, datatable.HeaderColumnNames())
|
||||
}
|
||||
|
||||
@@ -54,7 +68,34 @@ func TestCsvFileBasicDataTableRowIterator(t *testing.T) {
|
||||
{"A1", "B1", "C1"},
|
||||
{"A2", "B2", "C2"},
|
||||
{"A3", "B3", "C3"},
|
||||
})
|
||||
}, false)
|
||||
|
||||
iterator := datatable.DataRowIterator()
|
||||
assert.True(t, iterator.HasNext())
|
||||
|
||||
// data row 1
|
||||
assert.NotNil(t, iterator.Next())
|
||||
assert.True(t, iterator.HasNext())
|
||||
|
||||
// data row 2
|
||||
assert.NotNil(t, iterator.Next())
|
||||
assert.True(t, iterator.HasNext())
|
||||
|
||||
// data row 3
|
||||
assert.NotNil(t, iterator.Next())
|
||||
assert.False(t, iterator.HasNext())
|
||||
|
||||
// not existed data row 4
|
||||
assert.Nil(t, iterator.Next())
|
||||
assert.False(t, iterator.HasNext())
|
||||
}
|
||||
|
||||
func TestCsvFileBasicDataTableRowIterator_HasTitleLine(t *testing.T) {
|
||||
datatable := CreateNewCustomCsvBasicDataTable([][]string{
|
||||
{"A1", "B1", "C1"},
|
||||
{"A2", "B2", "C2"},
|
||||
{"A3", "B3", "C3"},
|
||||
}, true)
|
||||
|
||||
iterator := datatable.DataRowIterator()
|
||||
assert.True(t, iterator.HasNext())
|
||||
@@ -81,7 +122,7 @@ func TestCsvFileBasicDataTableRowColumnCount(t *testing.T) {
|
||||
{"A1", "B1", "C1"},
|
||||
{"A2", "B2", "C2"},
|
||||
{"A3", "B3", "C3"},
|
||||
})
|
||||
}, true)
|
||||
|
||||
iterator := datatable.DataRowIterator()
|
||||
|
||||
@@ -97,7 +138,32 @@ func TestCsvFileBasicDataTableRowGetData(t *testing.T) {
|
||||
{"A1", "B1", "C1"},
|
||||
{"A2", "B2", "C2"},
|
||||
{"A3", "B3", "C3"},
|
||||
})
|
||||
}, false)
|
||||
|
||||
iterator := datatable.DataRowIterator()
|
||||
|
||||
row1 := iterator.Next()
|
||||
assert.Equal(t, "A1", row1.GetData(0))
|
||||
assert.Equal(t, "B1", row1.GetData(1))
|
||||
assert.Equal(t, "C1", row1.GetData(2))
|
||||
|
||||
row2 := iterator.Next()
|
||||
assert.Equal(t, "A2", row2.GetData(0))
|
||||
assert.Equal(t, "B2", row2.GetData(1))
|
||||
assert.Equal(t, "C2", row2.GetData(2))
|
||||
|
||||
row3 := iterator.Next()
|
||||
assert.Equal(t, "A3", row3.GetData(0))
|
||||
assert.Equal(t, "B3", row3.GetData(1))
|
||||
assert.Equal(t, "C3", row3.GetData(2))
|
||||
}
|
||||
|
||||
func TestCsvFileBasicDataTableRowGetData_HasTitleLine(t *testing.T) {
|
||||
datatable := CreateNewCustomCsvBasicDataTable([][]string{
|
||||
{"A1", "B1", "C1"},
|
||||
{"A2", "B2", "C2"},
|
||||
{"A3", "B3", "C3"},
|
||||
}, true)
|
||||
|
||||
iterator := datatable.DataRowIterator()
|
||||
|
||||
@@ -117,7 +183,7 @@ func TestCsvFileBasicDataTableRowGetData_GetNotExistedColumnData(t *testing.T) {
|
||||
{"A1", "B1", "C1"},
|
||||
{"A2", "B2", "C2"},
|
||||
{"A3", "B3", "C3"},
|
||||
})
|
||||
}, true)
|
||||
|
||||
iterator := datatable.DataRowIterator()
|
||||
|
||||
@@ -130,7 +196,7 @@ func TestCreateNewCsvBasicDataTable(t *testing.T) {
|
||||
reader := bytes.NewReader([]byte("A1,B1,C1\n" +
|
||||
"A2,B2,C2\n" +
|
||||
"A3,B3,C3\n"))
|
||||
datatable, err := CreateNewCsvBasicDataTable(context, reader)
|
||||
datatable, err := CreateNewCsvBasicDataTable(context, reader, true)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, 2, datatable.DataRowCount())
|
||||
@@ -160,7 +226,7 @@ func TestCreateNewCsvBasicDataTable_SkipBlankLine(t *testing.T) {
|
||||
"A2,B2,C2\n" +
|
||||
"\n" +
|
||||
"A3,B3,C3\n"))
|
||||
datatable, err := CreateNewCsvBasicDataTable(context, reader)
|
||||
datatable, err := CreateNewCsvBasicDataTable(context, reader, true)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, 2, datatable.DataRowCount())
|
||||
|
||||
Reference in New Issue
Block a user