mirror of
https://github.com/ZeroHawkeye/wordZero.git
synced 2025-10-14 20:05:50 +08:00
在README.md和pkg/document/README.md中新增单元格遍历迭代器功能的详细描述,包括迭代器的创建、遍历、重置及查找功能;在pkg/document/table.go中实现CellIterator及相关方法,支持按行列遍历和条件查找单元格。
This commit is contained in:
18
README.md
18
README.md
@@ -197,6 +197,19 @@ wordZero/
|
||||
- [x] 表格位置信息获取
|
||||
- [x] 单元格访问接口
|
||||
- [x] 按行列索引访问
|
||||
- [x] **单元格遍历迭代器** ✨ **新实现**
|
||||
- [x] 单元格迭代器(CellIterator)
|
||||
- [x] 按顺序遍历所有单元格
|
||||
- [x] 迭代器重置和位置跟踪
|
||||
- [x] 迭代进度计算
|
||||
- [x] 单元格信息结构(CellInfo)
|
||||
- [x] ForEach批量处理方法
|
||||
- [x] 按行遍历(ForEachInRow)
|
||||
- [x] 按列遍历(ForEachInColumn)
|
||||
- [x] 获取单元格范围(GetCellRange)
|
||||
- [x] 条件查找单元格(FindCells)
|
||||
- [x] 按文本查找单元格(FindCellsByText)
|
||||
- [x] 精确匹配和模糊匹配支持
|
||||
|
||||
##### 表格样式和外观
|
||||
- [x] 表格整体样式
|
||||
@@ -240,7 +253,6 @@ wordZero/
|
||||
- [ ] 表格访问增强
|
||||
- [ ] 按标题查找表格
|
||||
- [ ] 按范围批量访问
|
||||
- [ ] 单元格遍历迭代器
|
||||
|
||||
#### 图片功能
|
||||
- [ ] 图片插入
|
||||
@@ -311,6 +323,7 @@ wordZero/
|
||||
- `examples/table_layout/` - 表格布局和尺寸演示
|
||||
- `examples/table_style/` - 表格样式和外观演示
|
||||
- `examples/cell_advanced/` - 单元格高级功能演示
|
||||
- `examples/cell_iterator/` - **单元格迭代器功能演示** ✨ **新增**
|
||||
- `examples/formatting/` - 格式化演示
|
||||
- `examples/page_settings/` - **页面设置演示** ✨ **新增**
|
||||
- `examples/advanced_features/` - **高级功能综合演示** ✨ **新增**
|
||||
@@ -340,6 +353,9 @@ go run ./examples/table_style/
|
||||
# 运行单元格高级功能演示
|
||||
go run ./examples/cell_advanced/
|
||||
|
||||
# 运行单元格迭代器功能演示
|
||||
go run ./examples/cell_iterator/
|
||||
|
||||
# 运行格式化演示
|
||||
go run ./examples/formatting/
|
||||
|
||||
|
187
examples/cell_iterator/main.go
Normal file
187
examples/cell_iterator/main.go
Normal file
@@ -0,0 +1,187 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/ZeroHawkeye/wordZero/pkg/document"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println("=== 单元格迭代器功能演示 ===")
|
||||
|
||||
// 创建新文档
|
||||
doc := document.New()
|
||||
|
||||
// 创建一个3x4的测试表格
|
||||
config := &document.TableConfig{
|
||||
Rows: 3,
|
||||
Cols: 4,
|
||||
Width: 8000,
|
||||
Data: [][]string{
|
||||
{"产品", "价格", "数量", "总计"},
|
||||
{"苹果", "5.00", "10", "50.00"},
|
||||
{"橙子", "3.50", "15", "52.50"},
|
||||
},
|
||||
}
|
||||
|
||||
table := doc.AddTable(config)
|
||||
if table == nil {
|
||||
log.Fatal("创建表格失败")
|
||||
}
|
||||
|
||||
fmt.Printf("创建了 %dx%d 的表格\n", table.GetRowCount(), table.GetColumnCount())
|
||||
|
||||
// 演示1: 基本迭代器使用
|
||||
fmt.Println("\n--- 1. 基本迭代器遍历 ---")
|
||||
iterator := table.NewCellIterator()
|
||||
fmt.Printf("表格总共有 %d 个单元格\n", iterator.Total())
|
||||
|
||||
cellCount := 0
|
||||
for iterator.HasNext() {
|
||||
cellInfo, err := iterator.Next()
|
||||
if err != nil {
|
||||
log.Printf("迭代器错误: %v", err)
|
||||
break
|
||||
}
|
||||
|
||||
cellCount++
|
||||
fmt.Printf("单元格[%d,%d]: '%s'", cellInfo.Row, cellInfo.Col, cellInfo.Text)
|
||||
|
||||
if cellInfo.IsLast {
|
||||
fmt.Print(" (最后一个)")
|
||||
}
|
||||
|
||||
fmt.Printf(" - 进度: %.1f%%\n", iterator.Progress()*100)
|
||||
}
|
||||
|
||||
// 演示2: 重置迭代器
|
||||
fmt.Println("\n--- 2. 重置迭代器演示 ---")
|
||||
iterator.Reset()
|
||||
row, col := iterator.Current()
|
||||
fmt.Printf("重置后,当前位置: (%d, %d)\n", row, col)
|
||||
|
||||
// 只遍历前3个单元格
|
||||
for i := 0; i < 3 && iterator.HasNext(); i++ {
|
||||
cellInfo, _ := iterator.Next()
|
||||
fmt.Printf("单元格[%d,%d]: '%s'\n", cellInfo.Row, cellInfo.Col, cellInfo.Text)
|
||||
}
|
||||
|
||||
// 演示3: ForEach方法
|
||||
fmt.Println("\n--- 3. ForEach 批量处理演示 ---")
|
||||
err := table.ForEach(func(row, col int, cell *document.TableCell, text string) error {
|
||||
if text != "" {
|
||||
fmt.Printf("处理单元格[%d,%d]: '%s' (长度: %d)\n", row, col, text, len(text))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.Printf("ForEach执行失败: %v", err)
|
||||
}
|
||||
|
||||
// 演示4: 按行遍历
|
||||
fmt.Println("\n--- 4. 按行遍历演示 ---")
|
||||
for row := 0; row < table.GetRowCount(); row++ {
|
||||
fmt.Printf("第%d行: ", row+1)
|
||||
err := table.ForEachInRow(row, func(col int, cell *document.TableCell, text string) error {
|
||||
fmt.Printf("'%s' ", text)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("按行遍历失败: %v", err)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// 演示5: 按列遍历
|
||||
fmt.Println("\n--- 5. 按列遍历演示 ---")
|
||||
for col := 0; col < table.GetColumnCount(); col++ {
|
||||
fmt.Printf("第%d列: ", col+1)
|
||||
err := table.ForEachInColumn(col, func(row int, cell *document.TableCell, text string) error {
|
||||
fmt.Printf("'%s' ", text)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("按列遍历失败: %v", err)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
// 演示6: 获取范围单元格
|
||||
fmt.Println("\n--- 6. 获取单元格范围演示 ---")
|
||||
cells, err := table.GetCellRange(1, 1, 2, 3) // 获取价格、数量、总计的数据部分
|
||||
if err != nil {
|
||||
log.Printf("获取范围失败: %v", err)
|
||||
} else {
|
||||
fmt.Printf("范围 (1,1) 到 (2,3) 的单元格:\n")
|
||||
for _, cellInfo := range cells {
|
||||
fmt.Printf(" [%d,%d]: '%s'\n", cellInfo.Row, cellInfo.Col, cellInfo.Text)
|
||||
}
|
||||
}
|
||||
|
||||
// 演示7: 查找单元格
|
||||
fmt.Println("\n--- 7. 查找单元格演示 ---")
|
||||
|
||||
// 查找包含数字的单元格
|
||||
numberCells, err := table.FindCells(func(row, col int, cell *document.TableCell, text string) bool {
|
||||
// 简单检查是否包含数字字符
|
||||
for _, char := range text {
|
||||
if char >= '0' && char <= '9' {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.Printf("查找失败: %v", err)
|
||||
} else {
|
||||
fmt.Printf("找到 %d 个包含数字的单元格:\n", len(numberCells))
|
||||
for _, cellInfo := range numberCells {
|
||||
fmt.Printf(" [%d,%d]: '%s'\n", cellInfo.Row, cellInfo.Col, cellInfo.Text)
|
||||
}
|
||||
}
|
||||
|
||||
// 演示8: 按文本查找
|
||||
fmt.Println("\n--- 8. 按文本查找演示 ---")
|
||||
|
||||
// 精确查找
|
||||
exactCells, err := table.FindCellsByText("苹果", true)
|
||||
if err != nil {
|
||||
log.Printf("精确查找失败: %v", err)
|
||||
} else {
|
||||
fmt.Printf("精确匹配 '苹果' 的单元格: %d 个\n", len(exactCells))
|
||||
for _, cellInfo := range exactCells {
|
||||
fmt.Printf(" [%d,%d]: '%s'\n", cellInfo.Row, cellInfo.Col, cellInfo.Text)
|
||||
}
|
||||
}
|
||||
|
||||
// 模糊查找
|
||||
fuzzyCells, err := table.FindCellsByText("5", false)
|
||||
if err != nil {
|
||||
log.Printf("模糊查找失败: %v", err)
|
||||
} else {
|
||||
fmt.Printf("包含 '5' 的单元格: %d 个\n", len(fuzzyCells))
|
||||
for _, cellInfo := range fuzzyCells {
|
||||
fmt.Printf(" [%d,%d]: '%s'\n", cellInfo.Row, cellInfo.Col, cellInfo.Text)
|
||||
}
|
||||
}
|
||||
|
||||
// 保存文档
|
||||
outputDir := "examples/output"
|
||||
if err := os.MkdirAll(outputDir, 0755); err != nil {
|
||||
log.Printf("创建输出目录失败: %v", err)
|
||||
}
|
||||
|
||||
filename := filepath.Join(outputDir, "cell_iterator_demo.docx")
|
||||
if err := doc.Save(filename); err != nil {
|
||||
log.Printf("保存文档失败: %v", err)
|
||||
} else {
|
||||
fmt.Printf("\n文档已保存到: %s\n", filename)
|
||||
}
|
||||
|
||||
fmt.Println("\n=== 单元格迭代器演示完成 ===")
|
||||
}
|
@@ -220,6 +220,84 @@
|
||||
- [`SetCellShading(row, col int, config *ShadingConfig)`](table.go#L2121) - 设置单元格底纹
|
||||
- [`SetAlternatingRowColors(evenRowColor, oddRowColor string)`](table.go#L2142) - 设置交替行颜色
|
||||
|
||||
### 单元格遍历迭代器 ✨ **新功能**
|
||||
|
||||
提供强大的单元格遍历和查找功能:
|
||||
|
||||
##### CellIterator - 单元格迭代器
|
||||
```go
|
||||
// 创建迭代器
|
||||
iterator := table.NewCellIterator()
|
||||
|
||||
// 遍历所有单元格
|
||||
for iterator.HasNext() {
|
||||
cellInfo, err := iterator.Next()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
fmt.Printf("单元格[%d,%d]: %s\n", cellInfo.Row, cellInfo.Col, cellInfo.Text)
|
||||
}
|
||||
|
||||
// 获取进度
|
||||
progress := iterator.Progress() // 0.0 - 1.0
|
||||
|
||||
// 重置迭代器
|
||||
iterator.Reset()
|
||||
```
|
||||
|
||||
##### ForEach 批量处理
|
||||
```go
|
||||
// 遍历所有单元格
|
||||
err := table.ForEach(func(row, col int, cell *TableCell, text string) error {
|
||||
// 处理每个单元格
|
||||
return nil
|
||||
})
|
||||
|
||||
// 按行遍历
|
||||
err := table.ForEachInRow(rowIndex, func(col int, cell *TableCell, text string) error {
|
||||
// 处理行中的每个单元格
|
||||
return nil
|
||||
})
|
||||
|
||||
// 按列遍历
|
||||
err := table.ForEachInColumn(colIndex, func(row int, cell *TableCell, text string) error {
|
||||
// 处理列中的每个单元格
|
||||
return nil
|
||||
})
|
||||
```
|
||||
|
||||
##### 范围操作
|
||||
```go
|
||||
// 获取指定范围的单元格
|
||||
cells, err := table.GetCellRange(startRow, startCol, endRow, endCol)
|
||||
for _, cellInfo := range cells {
|
||||
fmt.Printf("单元格[%d,%d]: %s\n", cellInfo.Row, cellInfo.Col, cellInfo.Text)
|
||||
}
|
||||
```
|
||||
|
||||
##### 查找功能
|
||||
```go
|
||||
// 自定义条件查找
|
||||
cells, err := table.FindCells(func(row, col int, cell *TableCell, text string) bool {
|
||||
return strings.Contains(text, "关键词")
|
||||
})
|
||||
|
||||
// 按文本查找
|
||||
exactCells, err := table.FindCellsByText("精确匹配", true)
|
||||
fuzzyCells, err := table.FindCellsByText("模糊", false)
|
||||
```
|
||||
|
||||
##### CellInfo 结构
|
||||
```go
|
||||
type CellInfo struct {
|
||||
Row int // 行索引
|
||||
Col int // 列索引
|
||||
Cell *TableCell // 单元格引用
|
||||
Text string // 单元格文本
|
||||
IsLast bool // 是否为最后一个单元格
|
||||
}
|
||||
```
|
||||
|
||||
## 工具函数
|
||||
|
||||
### 日志系统
|
||||
|
@@ -4,6 +4,7 @@ package document
|
||||
import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Table 表示一个表格
|
||||
@@ -2320,3 +2321,249 @@ func createTableCellBorder(config *BorderConfig) *TableCellBorder {
|
||||
Color: config.Color,
|
||||
}
|
||||
}
|
||||
|
||||
// CellIterator 单元格迭代器
|
||||
type CellIterator struct {
|
||||
table *Table
|
||||
currentRow int
|
||||
currentCol int
|
||||
totalRows int
|
||||
totalCols int
|
||||
}
|
||||
|
||||
// CellInfo 单元格信息
|
||||
type CellInfo struct {
|
||||
Row int // 行索引
|
||||
Col int // 列索引
|
||||
Cell *TableCell // 单元格引用
|
||||
Text string // 单元格文本
|
||||
IsLast bool // 是否为最后一个单元格
|
||||
}
|
||||
|
||||
// NewCellIterator 创建新的单元格迭代器
|
||||
func (t *Table) NewCellIterator() *CellIterator {
|
||||
totalRows := t.GetRowCount()
|
||||
totalCols := 0
|
||||
if totalRows > 0 {
|
||||
totalCols = t.GetColumnCount()
|
||||
}
|
||||
|
||||
return &CellIterator{
|
||||
table: t,
|
||||
currentRow: 0,
|
||||
currentCol: 0,
|
||||
totalRows: totalRows,
|
||||
totalCols: totalCols,
|
||||
}
|
||||
}
|
||||
|
||||
// HasNext 检查是否还有下一个单元格
|
||||
func (iter *CellIterator) HasNext() bool {
|
||||
if iter.totalRows == 0 || iter.totalCols == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
// 检查当前位置是否超出范围
|
||||
return iter.currentRow < iter.totalRows &&
|
||||
(iter.currentRow < iter.totalRows-1 || iter.currentCol < iter.totalCols)
|
||||
}
|
||||
|
||||
// Next 获取下一个单元格信息
|
||||
func (iter *CellIterator) Next() (*CellInfo, error) {
|
||||
if !iter.HasNext() {
|
||||
return nil, fmt.Errorf("没有更多单元格")
|
||||
}
|
||||
|
||||
// 获取当前单元格
|
||||
cell, err := iter.table.GetCell(iter.currentRow, iter.currentCol)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取单元格失败: %v", err)
|
||||
}
|
||||
|
||||
// 获取单元格文本
|
||||
text, _ := iter.table.GetCellText(iter.currentRow, iter.currentCol)
|
||||
|
||||
// 创建单元格信息
|
||||
cellInfo := &CellInfo{
|
||||
Row: iter.currentRow,
|
||||
Col: iter.currentCol,
|
||||
Cell: cell,
|
||||
Text: text,
|
||||
}
|
||||
|
||||
// 更新位置并检查是否为最后一个
|
||||
iter.currentCol++
|
||||
if iter.currentCol >= iter.totalCols {
|
||||
iter.currentCol = 0
|
||||
iter.currentRow++
|
||||
}
|
||||
|
||||
// 检查是否为最后一个单元格
|
||||
cellInfo.IsLast = !iter.HasNext()
|
||||
|
||||
return cellInfo, nil
|
||||
}
|
||||
|
||||
// Reset 重置迭代器到开始位置
|
||||
func (iter *CellIterator) Reset() {
|
||||
iter.currentRow = 0
|
||||
iter.currentCol = 0
|
||||
}
|
||||
|
||||
// Current 获取当前位置信息(不移动迭代器)
|
||||
func (iter *CellIterator) Current() (int, int) {
|
||||
return iter.currentRow, iter.currentCol
|
||||
}
|
||||
|
||||
// Total 获取总单元格数量
|
||||
func (iter *CellIterator) Total() int {
|
||||
return iter.totalRows * iter.totalCols
|
||||
}
|
||||
|
||||
// Progress 获取迭代进度(0.0-1.0)
|
||||
func (iter *CellIterator) Progress() float64 {
|
||||
if iter.totalRows == 0 || iter.totalCols == 0 {
|
||||
return 1.0
|
||||
}
|
||||
|
||||
processed := iter.currentRow*iter.totalCols + iter.currentCol
|
||||
total := iter.totalRows * iter.totalCols
|
||||
|
||||
return float64(processed) / float64(total)
|
||||
}
|
||||
|
||||
// ForEach 遍历所有单元格,对每个单元格执行指定函数
|
||||
func (t *Table) ForEach(fn func(row, col int, cell *TableCell, text string) error) error {
|
||||
iterator := t.NewCellIterator()
|
||||
|
||||
for iterator.HasNext() {
|
||||
cellInfo, err := iterator.Next()
|
||||
if err != nil {
|
||||
return fmt.Errorf("迭代失败: %v", err)
|
||||
}
|
||||
|
||||
if err := fn(cellInfo.Row, cellInfo.Col, cellInfo.Cell, cellInfo.Text); err != nil {
|
||||
return fmt.Errorf("回调函数执行失败 (行:%d, 列:%d): %v", cellInfo.Row, cellInfo.Col, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ForEachInRow 遍历指定行的所有单元格
|
||||
func (t *Table) ForEachInRow(rowIndex int, fn func(col int, cell *TableCell, text string) error) error {
|
||||
if rowIndex < 0 || rowIndex >= t.GetRowCount() {
|
||||
return fmt.Errorf("行索引无效: %d", rowIndex)
|
||||
}
|
||||
|
||||
colCount := t.GetColumnCount()
|
||||
for col := 0; col < colCount; col++ {
|
||||
cell, err := t.GetCell(rowIndex, col)
|
||||
if err != nil {
|
||||
return fmt.Errorf("获取单元格失败 (行:%d, 列:%d): %v", rowIndex, col, err)
|
||||
}
|
||||
|
||||
text, _ := t.GetCellText(rowIndex, col)
|
||||
|
||||
if err := fn(col, cell, text); err != nil {
|
||||
return fmt.Errorf("回调函数执行失败 (行:%d, 列:%d): %v", rowIndex, col, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ForEachInColumn 遍历指定列的所有单元格
|
||||
func (t *Table) ForEachInColumn(colIndex int, fn func(row int, cell *TableCell, text string) error) error {
|
||||
if colIndex < 0 || colIndex >= t.GetColumnCount() {
|
||||
return fmt.Errorf("列索引无效: %d", colIndex)
|
||||
}
|
||||
|
||||
rowCount := t.GetRowCount()
|
||||
for row := 0; row < rowCount; row++ {
|
||||
cell, err := t.GetCell(row, colIndex)
|
||||
if err != nil {
|
||||
return fmt.Errorf("获取单元格失败 (行:%d, 列:%d): %v", row, colIndex, err)
|
||||
}
|
||||
|
||||
text, _ := t.GetCellText(row, colIndex)
|
||||
|
||||
if err := fn(row, cell, text); err != nil {
|
||||
return fmt.Errorf("回调函数执行失败 (行:%d, 列:%d): %v", row, colIndex, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetCellRange 获取指定范围内的所有单元格
|
||||
func (t *Table) GetCellRange(startRow, startCol, endRow, endCol int) ([]*CellInfo, error) {
|
||||
// 参数验证
|
||||
if startRow < 0 || startCol < 0 || endRow >= t.GetRowCount() || endCol >= t.GetColumnCount() {
|
||||
return nil, fmt.Errorf("范围索引无效: (%d,%d) 到 (%d,%d)", startRow, startCol, endRow, endCol)
|
||||
}
|
||||
|
||||
if startRow > endRow || startCol > endCol {
|
||||
return nil, fmt.Errorf("开始位置不能大于结束位置")
|
||||
}
|
||||
|
||||
var cells []*CellInfo
|
||||
|
||||
for row := startRow; row <= endRow; row++ {
|
||||
for col := startCol; col <= endCol; col++ {
|
||||
cell, err := t.GetCell(row, col)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取单元格失败 (行:%d, 列:%d): %v", row, col, err)
|
||||
}
|
||||
|
||||
text, _ := t.GetCellText(row, col)
|
||||
|
||||
cellInfo := &CellInfo{
|
||||
Row: row,
|
||||
Col: col,
|
||||
Cell: cell,
|
||||
Text: text,
|
||||
IsLast: row == endRow && col == endCol,
|
||||
}
|
||||
|
||||
cells = append(cells, cellInfo)
|
||||
}
|
||||
}
|
||||
|
||||
return cells, nil
|
||||
}
|
||||
|
||||
// FindCells 查找满足条件的单元格
|
||||
func (t *Table) FindCells(predicate func(row, col int, cell *TableCell, text string) bool) ([]*CellInfo, error) {
|
||||
var matchedCells []*CellInfo
|
||||
|
||||
err := t.ForEach(func(row, col int, cell *TableCell, text string) error {
|
||||
if predicate(row, col, cell, text) {
|
||||
cellInfo := &CellInfo{
|
||||
Row: row,
|
||||
Col: col,
|
||||
Cell: cell,
|
||||
Text: text,
|
||||
}
|
||||
matchedCells = append(matchedCells, cellInfo)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return matchedCells, nil
|
||||
}
|
||||
|
||||
// FindCellsByText 根据文本内容查找单元格
|
||||
func (t *Table) FindCellsByText(searchText string, exactMatch bool) ([]*CellInfo, error) {
|
||||
return t.FindCells(func(row, col int, cell *TableCell, text string) bool {
|
||||
if exactMatch {
|
||||
return text == searchText
|
||||
}
|
||||
// 使用strings.Contains进行模糊匹配
|
||||
return strings.Contains(text, searchText)
|
||||
})
|
||||
}
|
||||
|
466
pkg/document/table_iterator_test.go
Normal file
466
pkg/document/table_iterator_test.go
Normal file
@@ -0,0 +1,466 @@
|
||||
package document
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestCellIterator 测试基本的单元格迭代器功能
|
||||
func TestCellIterator(t *testing.T) {
|
||||
// 创建一个3x3的测试表格
|
||||
doc := New()
|
||||
config := &TableConfig{
|
||||
Rows: 3,
|
||||
Cols: 3,
|
||||
Width: 5000,
|
||||
Data: [][]string{
|
||||
{"A1", "B1", "C1"},
|
||||
{"A2", "B2", "C2"},
|
||||
{"A3", "B3", "C3"},
|
||||
},
|
||||
}
|
||||
|
||||
table := doc.CreateTable(config)
|
||||
if table == nil {
|
||||
t.Fatal("创建表格失败")
|
||||
}
|
||||
|
||||
// 测试迭代器创建
|
||||
iterator := table.NewCellIterator()
|
||||
if iterator == nil {
|
||||
t.Fatal("创建迭代器失败")
|
||||
}
|
||||
|
||||
// 测试Total方法
|
||||
expectedTotal := 9
|
||||
if iterator.Total() != expectedTotal {
|
||||
t.Errorf("Total()期望返回%d,实际返回%d", expectedTotal, iterator.Total())
|
||||
}
|
||||
|
||||
// 测试迭代器遍历
|
||||
cellCount := 0
|
||||
expectedCells := []struct {
|
||||
row int
|
||||
col int
|
||||
text string
|
||||
}{
|
||||
{0, 0, "A1"}, {0, 1, "B1"}, {0, 2, "C1"},
|
||||
{1, 0, "A2"}, {1, 1, "B2"}, {1, 2, "C2"},
|
||||
{2, 0, "A3"}, {2, 1, "B3"}, {2, 2, "C3"},
|
||||
}
|
||||
|
||||
for iterator.HasNext() {
|
||||
cellInfo, err := iterator.Next()
|
||||
if err != nil {
|
||||
t.Fatalf("迭代器Next()失败: %v", err)
|
||||
}
|
||||
|
||||
if cellCount >= len(expectedCells) {
|
||||
t.Fatalf("迭代器返回了过多的单元格")
|
||||
}
|
||||
|
||||
expected := expectedCells[cellCount]
|
||||
if cellInfo.Row != expected.row || cellInfo.Col != expected.col {
|
||||
t.Errorf("单元格位置不匹配: 期望(%d,%d),实际(%d,%d)",
|
||||
expected.row, expected.col, cellInfo.Row, cellInfo.Col)
|
||||
}
|
||||
|
||||
if cellInfo.Text != expected.text {
|
||||
t.Errorf("单元格文本不匹配: 期望'%s',实际'%s'",
|
||||
expected.text, cellInfo.Text)
|
||||
}
|
||||
|
||||
if cellInfo.Cell == nil {
|
||||
t.Error("单元格引用为nil")
|
||||
}
|
||||
|
||||
// 测试IsLast标记
|
||||
if cellCount == len(expectedCells)-1 && !cellInfo.IsLast {
|
||||
t.Error("最后一个单元格的IsLast标记应为true")
|
||||
}
|
||||
|
||||
cellCount++
|
||||
}
|
||||
|
||||
if cellCount != expectedTotal {
|
||||
t.Errorf("迭代的单元格数量不匹配: 期望%d,实际%d", expectedTotal, cellCount)
|
||||
}
|
||||
}
|
||||
|
||||
// TestCellIteratorReset 测试迭代器重置功能
|
||||
func TestCellIteratorReset(t *testing.T) {
|
||||
doc := New()
|
||||
config := &TableConfig{
|
||||
Rows: 2,
|
||||
Cols: 2,
|
||||
Width: 3000,
|
||||
Data: [][]string{
|
||||
{"A1", "B1"},
|
||||
{"A2", "B2"},
|
||||
},
|
||||
}
|
||||
|
||||
table := doc.CreateTable(config)
|
||||
iterator := table.NewCellIterator()
|
||||
|
||||
// 先迭代一些单元格
|
||||
iterator.Next()
|
||||
iterator.Next()
|
||||
|
||||
// 检查当前位置
|
||||
row, col := iterator.Current()
|
||||
if row != 1 || col != 0 {
|
||||
t.Errorf("迭代器位置不正确: 期望(1,0),实际(%d,%d)", row, col)
|
||||
}
|
||||
|
||||
// 重置迭代器
|
||||
iterator.Reset()
|
||||
|
||||
// 检查重置后的位置
|
||||
row, col = iterator.Current()
|
||||
if row != 0 || col != 0 {
|
||||
t.Errorf("重置后位置不正确: 期望(0,0),实际(%d,%d)", row, col)
|
||||
}
|
||||
|
||||
// 确保能重新遍历
|
||||
if !iterator.HasNext() {
|
||||
t.Error("重置后应该有下一个单元格")
|
||||
}
|
||||
}
|
||||
|
||||
// TestCellIteratorProgress 测试进度计算
|
||||
func TestCellIteratorProgress(t *testing.T) {
|
||||
doc := New()
|
||||
config := &TableConfig{
|
||||
Rows: 2,
|
||||
Cols: 2,
|
||||
Width: 3000,
|
||||
}
|
||||
|
||||
table := doc.CreateTable(config)
|
||||
iterator := table.NewCellIterator()
|
||||
|
||||
// 初始进度应为0
|
||||
if iterator.Progress() != 0.0 {
|
||||
t.Errorf("初始进度应为0.0,实际为%f", iterator.Progress())
|
||||
}
|
||||
|
||||
// 迭代一个单元格
|
||||
iterator.Next()
|
||||
expectedProgress := 0.25 // 1/4
|
||||
if iterator.Progress() != expectedProgress {
|
||||
t.Errorf("迭代一个单元格后进度应为%f,实际为%f", expectedProgress, iterator.Progress())
|
||||
}
|
||||
|
||||
// 迭代到最后
|
||||
for iterator.HasNext() {
|
||||
iterator.Next()
|
||||
}
|
||||
|
||||
if iterator.Progress() != 1.0 {
|
||||
t.Errorf("完成迭代后进度应为1.0,实际为%f", iterator.Progress())
|
||||
}
|
||||
}
|
||||
|
||||
// TestTableForEach 测试ForEach方法
|
||||
func TestTableForEach(t *testing.T) {
|
||||
doc := New()
|
||||
config := &TableConfig{
|
||||
Rows: 2,
|
||||
Cols: 3,
|
||||
Width: 4000,
|
||||
Data: [][]string{
|
||||
{"A1", "B1", "C1"},
|
||||
{"A2", "B2", "C2"},
|
||||
},
|
||||
}
|
||||
|
||||
table := doc.CreateTable(config)
|
||||
|
||||
// 测试ForEach遍历
|
||||
var visitedCells []string
|
||||
err := table.ForEach(func(row, col int, cell *TableCell, text string) error {
|
||||
visitedCells = append(visitedCells, fmt.Sprintf("%d-%d:%s", row, col, text))
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("ForEach执行失败: %v", err)
|
||||
}
|
||||
|
||||
expectedCells := []string{
|
||||
"0-0:A1", "0-1:B1", "0-2:C1",
|
||||
"1-0:A2", "1-1:B2", "1-2:C2",
|
||||
}
|
||||
|
||||
if len(visitedCells) != len(expectedCells) {
|
||||
t.Errorf("访问的单元格数量不匹配: 期望%d,实际%d", len(expectedCells), len(visitedCells))
|
||||
}
|
||||
|
||||
for i, expected := range expectedCells {
|
||||
if i < len(visitedCells) && visitedCells[i] != expected {
|
||||
t.Errorf("单元格访问顺序不正确: 期望'%s',实际'%s'", expected, visitedCells[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestForEachInRow 测试按行遍历
|
||||
func TestForEachInRow(t *testing.T) {
|
||||
doc := New()
|
||||
config := &TableConfig{
|
||||
Rows: 3,
|
||||
Cols: 3,
|
||||
Width: 4000,
|
||||
Data: [][]string{
|
||||
{"A1", "B1", "C1"},
|
||||
{"A2", "B2", "C2"},
|
||||
{"A3", "B3", "C3"},
|
||||
},
|
||||
}
|
||||
|
||||
table := doc.CreateTable(config)
|
||||
|
||||
// 测试遍历第2行(索引1)
|
||||
var visitedCells []string
|
||||
err := table.ForEachInRow(1, func(col int, cell *TableCell, text string) error {
|
||||
visitedCells = append(visitedCells, fmt.Sprintf("%d:%s", col, text))
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("ForEachInRow执行失败: %v", err)
|
||||
}
|
||||
|
||||
expectedCells := []string{"0:A2", "1:B2", "2:C2"}
|
||||
if len(visitedCells) != len(expectedCells) {
|
||||
t.Errorf("访问的单元格数量不匹配: 期望%d,实际%d", len(expectedCells), len(visitedCells))
|
||||
}
|
||||
|
||||
for i, expected := range expectedCells {
|
||||
if i < len(visitedCells) && visitedCells[i] != expected {
|
||||
t.Errorf("单元格访问顺序不正确: 期望'%s',实际'%s'", expected, visitedCells[i])
|
||||
}
|
||||
}
|
||||
|
||||
// 测试无效行索引
|
||||
err = table.ForEachInRow(5, func(col int, cell *TableCell, text string) error {
|
||||
return nil
|
||||
})
|
||||
if err == nil {
|
||||
t.Error("应该返回无效行索引错误")
|
||||
}
|
||||
}
|
||||
|
||||
// TestForEachInColumn 测试按列遍历
|
||||
func TestForEachInColumn(t *testing.T) {
|
||||
doc := New()
|
||||
config := &TableConfig{
|
||||
Rows: 3,
|
||||
Cols: 3,
|
||||
Width: 4000,
|
||||
Data: [][]string{
|
||||
{"A1", "B1", "C1"},
|
||||
{"A2", "B2", "C2"},
|
||||
{"A3", "B3", "C3"},
|
||||
},
|
||||
}
|
||||
|
||||
table := doc.CreateTable(config)
|
||||
|
||||
// 测试遍历第2列(索引1)
|
||||
var visitedCells []string
|
||||
err := table.ForEachInColumn(1, func(row int, cell *TableCell, text string) error {
|
||||
visitedCells = append(visitedCells, fmt.Sprintf("%d:%s", row, text))
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("ForEachInColumn执行失败: %v", err)
|
||||
}
|
||||
|
||||
expectedCells := []string{"0:B1", "1:B2", "2:B3"}
|
||||
if len(visitedCells) != len(expectedCells) {
|
||||
t.Errorf("访问的单元格数量不匹配: 期望%d,实际%d", len(expectedCells), len(visitedCells))
|
||||
}
|
||||
|
||||
for i, expected := range expectedCells {
|
||||
if i < len(visitedCells) && visitedCells[i] != expected {
|
||||
t.Errorf("单元格访问顺序不正确: 期望'%s',实际'%s'", expected, visitedCells[i])
|
||||
}
|
||||
}
|
||||
|
||||
// 测试无效列索引
|
||||
err = table.ForEachInColumn(5, func(row int, cell *TableCell, text string) error {
|
||||
return nil
|
||||
})
|
||||
if err == nil {
|
||||
t.Error("应该返回无效列索引错误")
|
||||
}
|
||||
}
|
||||
|
||||
// TestGetCellRange 测试获取单元格范围
|
||||
func TestGetCellRange(t *testing.T) {
|
||||
doc := New()
|
||||
config := &TableConfig{
|
||||
Rows: 4,
|
||||
Cols: 4,
|
||||
Width: 5000,
|
||||
Data: [][]string{
|
||||
{"A1", "B1", "C1", "D1"},
|
||||
{"A2", "B2", "C2", "D2"},
|
||||
{"A3", "B3", "C3", "D3"},
|
||||
{"A4", "B4", "C4", "D4"},
|
||||
},
|
||||
}
|
||||
|
||||
table := doc.CreateTable(config)
|
||||
|
||||
// 测试获取2x2范围 (1,1) 到 (2,2)
|
||||
cells, err := table.GetCellRange(1, 1, 2, 2)
|
||||
if err != nil {
|
||||
t.Fatalf("GetCellRange执行失败: %v", err)
|
||||
}
|
||||
|
||||
expectedCells := []struct {
|
||||
row int
|
||||
col int
|
||||
text string
|
||||
}{
|
||||
{1, 1, "B2"}, {1, 2, "C2"},
|
||||
{2, 1, "B3"}, {2, 2, "C3"},
|
||||
}
|
||||
|
||||
if len(cells) != len(expectedCells) {
|
||||
t.Errorf("返回的单元格数量不匹配: 期望%d,实际%d", len(expectedCells), len(cells))
|
||||
}
|
||||
|
||||
for i, expected := range expectedCells {
|
||||
if i < len(cells) {
|
||||
cell := cells[i]
|
||||
if cell.Row != expected.row || cell.Col != expected.col {
|
||||
t.Errorf("单元格位置不匹配: 期望(%d,%d),实际(%d,%d)",
|
||||
expected.row, expected.col, cell.Row, cell.Col)
|
||||
}
|
||||
if cell.Text != expected.text {
|
||||
t.Errorf("单元格文本不匹配: 期望'%s',实际'%s'",
|
||||
expected.text, cell.Text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 测试无效范围
|
||||
_, err = table.GetCellRange(2, 2, 1, 1) // 开始位置大于结束位置
|
||||
if err == nil {
|
||||
t.Error("应该返回无效范围错误")
|
||||
}
|
||||
|
||||
_, err = table.GetCellRange(0, 0, 10, 10) // 超出表格范围
|
||||
if err == nil {
|
||||
t.Error("应该返回超出范围错误")
|
||||
}
|
||||
}
|
||||
|
||||
// TestFindCells 测试查找单元格功能
|
||||
func TestFindCells(t *testing.T) {
|
||||
doc := New()
|
||||
config := &TableConfig{
|
||||
Rows: 3,
|
||||
Cols: 3,
|
||||
Width: 4000,
|
||||
Data: [][]string{
|
||||
{"apple", "banana", "cherry"},
|
||||
{"dog", "apple", "fish"},
|
||||
{"grape", "horse", "apple"},
|
||||
},
|
||||
}
|
||||
|
||||
table := doc.CreateTable(config)
|
||||
|
||||
// 查找包含"apple"的单元格
|
||||
cells, err := table.FindCells(func(row, col int, cell *TableCell, text string) bool {
|
||||
return text == "apple"
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("FindCells执行失败: %v", err)
|
||||
}
|
||||
|
||||
expectedPositions := [][2]int{{0, 0}, {1, 1}, {2, 2}}
|
||||
if len(cells) != len(expectedPositions) {
|
||||
t.Errorf("找到的单元格数量不匹配: 期望%d,实际%d", len(expectedPositions), len(cells))
|
||||
}
|
||||
|
||||
for i, expected := range expectedPositions {
|
||||
if i < len(cells) {
|
||||
cell := cells[i]
|
||||
if cell.Row != expected[0] || cell.Col != expected[1] {
|
||||
t.Errorf("找到的单元格位置不正确: 期望(%d,%d),实际(%d,%d)",
|
||||
expected[0], expected[1], cell.Row, cell.Col)
|
||||
}
|
||||
if cell.Text != "apple" {
|
||||
t.Errorf("找到的单元格文本不正确: 期望'apple',实际'%s'", cell.Text)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestFindCellsByText 测试按文本查找单元格
|
||||
func TestFindCellsByText(t *testing.T) {
|
||||
doc := New()
|
||||
config := &TableConfig{
|
||||
Rows: 2,
|
||||
Cols: 3,
|
||||
Width: 4000,
|
||||
Data: [][]string{
|
||||
{"test", "testing", "other"},
|
||||
{"notest", "test123", "test"},
|
||||
},
|
||||
}
|
||||
|
||||
table := doc.CreateTable(config)
|
||||
|
||||
// 精确匹配
|
||||
cells, err := table.FindCellsByText("test", true)
|
||||
if err != nil {
|
||||
t.Fatalf("FindCellsByText执行失败: %v", err)
|
||||
}
|
||||
|
||||
expectedCount := 2 // (0,0) 和 (1,2)
|
||||
if len(cells) != expectedCount {
|
||||
t.Errorf("精确匹配找到的单元格数量不匹配: 期望%d,实际%d", expectedCount, len(cells))
|
||||
}
|
||||
|
||||
// 模糊匹配
|
||||
cells, err = table.FindCellsByText("test", false)
|
||||
if err != nil {
|
||||
t.Fatalf("FindCellsByText执行失败: %v", err)
|
||||
}
|
||||
|
||||
expectedCount = 5 // 所有包含"test"的单元格
|
||||
if len(cells) != expectedCount {
|
||||
t.Errorf("模糊匹配找到的单元格数量不匹配: 期望%d,实际%d", expectedCount, len(cells))
|
||||
}
|
||||
}
|
||||
|
||||
// TestEmptyTable 测试空表格的迭代器
|
||||
func TestEmptyTable(t *testing.T) {
|
||||
doc := New()
|
||||
|
||||
// 创建一个空表格(实际上最小1x1)
|
||||
config := &TableConfig{
|
||||
Rows: 1,
|
||||
Cols: 1,
|
||||
Width: 2000,
|
||||
}
|
||||
|
||||
table := doc.CreateTable(config)
|
||||
iterator := table.NewCellIterator()
|
||||
|
||||
if iterator.Total() != 1 {
|
||||
t.Errorf("空表格的总单元格数应为1,实际为%d", iterator.Total())
|
||||
}
|
||||
|
||||
if !iterator.HasNext() {
|
||||
t.Error("1x1表格应该有一个单元格")
|
||||
}
|
||||
}
|
229
test/cell_iterator_integration_test.go
Normal file
229
test/cell_iterator_integration_test.go
Normal file
@@ -0,0 +1,229 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/ZeroHawkeye/wordZero/pkg/document"
|
||||
)
|
||||
|
||||
// TestCellIteratorIntegration 单元格迭代器功能集成测试
|
||||
func TestCellIteratorIntegration(t *testing.T) {
|
||||
// 创建测试文档
|
||||
doc := document.New()
|
||||
|
||||
// 创建测试表格
|
||||
config := &document.TableConfig{
|
||||
Rows: 4,
|
||||
Cols: 3,
|
||||
Width: 6000,
|
||||
Data: [][]string{
|
||||
{"姓名", "年龄", "城市"},
|
||||
{"张三", "25", "北京"},
|
||||
{"李四", "30", "上海"},
|
||||
{"王五", "28", "广州"},
|
||||
},
|
||||
}
|
||||
|
||||
table := doc.AddTable(config)
|
||||
if table == nil {
|
||||
t.Fatal("创建表格失败")
|
||||
}
|
||||
|
||||
// 测试1: 基本迭代器功能
|
||||
t.Run("基本迭代器", func(t *testing.T) {
|
||||
iterator := table.NewCellIterator()
|
||||
|
||||
// 验证总数
|
||||
expectedTotal := 12
|
||||
if iterator.Total() != expectedTotal {
|
||||
t.Errorf("总单元格数不正确: 期望%d,实际%d", expectedTotal, iterator.Total())
|
||||
}
|
||||
|
||||
// 验证完整遍历
|
||||
count := 0
|
||||
for iterator.HasNext() {
|
||||
cellInfo, err := iterator.Next()
|
||||
if err != nil {
|
||||
t.Errorf("迭代器错误: %v", err)
|
||||
break
|
||||
}
|
||||
|
||||
if cellInfo == nil {
|
||||
t.Error("单元格信息为空")
|
||||
continue
|
||||
}
|
||||
|
||||
if cellInfo.Cell == nil {
|
||||
t.Error("单元格引用为空")
|
||||
}
|
||||
|
||||
count++
|
||||
}
|
||||
|
||||
if count != expectedTotal {
|
||||
t.Errorf("实际遍历数量不正确: 期望%d,实际%d", expectedTotal, count)
|
||||
}
|
||||
})
|
||||
|
||||
// 测试2: 重置功能
|
||||
t.Run("迭代器重置", func(t *testing.T) {
|
||||
iterator := table.NewCellIterator()
|
||||
|
||||
// 迭代几个单元格
|
||||
iterator.Next()
|
||||
iterator.Next()
|
||||
|
||||
// 重置并验证
|
||||
iterator.Reset()
|
||||
row, col := iterator.Current()
|
||||
if row != 0 || col != 0 {
|
||||
t.Errorf("重置后位置不正确: 期望(0,0),实际(%d,%d)", row, col)
|
||||
}
|
||||
})
|
||||
|
||||
// 测试3: ForEach功能
|
||||
t.Run("ForEach遍历", func(t *testing.T) {
|
||||
visitedCount := 0
|
||||
err := table.ForEach(func(row, col int, cell *document.TableCell, text string) error {
|
||||
visitedCount++
|
||||
if cell == nil {
|
||||
t.Errorf("位置(%d,%d)的单元格为空", row, col)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("ForEach执行失败: %v", err)
|
||||
}
|
||||
|
||||
if visitedCount != 12 {
|
||||
t.Errorf("ForEach访问数量不正确: 期望12,实际%d", visitedCount)
|
||||
}
|
||||
})
|
||||
|
||||
// 测试4: 按行遍历
|
||||
t.Run("按行遍历", func(t *testing.T) {
|
||||
for row := 0; row < table.GetRowCount(); row++ {
|
||||
visitedCount := 0
|
||||
err := table.ForEachInRow(row, func(col int, cell *document.TableCell, text string) error {
|
||||
visitedCount++
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("第%d行遍历失败: %v", row, err)
|
||||
}
|
||||
|
||||
if visitedCount != 3 {
|
||||
t.Errorf("第%d行单元格数量不正确: 期望3,实际%d", row, visitedCount)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 测试5: 按列遍历
|
||||
t.Run("按列遍历", func(t *testing.T) {
|
||||
for col := 0; col < table.GetColumnCount(); col++ {
|
||||
visitedCount := 0
|
||||
err := table.ForEachInColumn(col, func(row int, cell *document.TableCell, text string) error {
|
||||
visitedCount++
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("第%d列遍历失败: %v", col, err)
|
||||
}
|
||||
|
||||
if visitedCount != 4 {
|
||||
t.Errorf("第%d列单元格数量不正确: 期望4,实际%d", col, visitedCount)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 测试6: 范围获取
|
||||
t.Run("单元格范围", func(t *testing.T) {
|
||||
// 获取数据区域 (1,0) 到 (3,2)
|
||||
cells, err := table.GetCellRange(1, 0, 3, 2)
|
||||
if err != nil {
|
||||
t.Errorf("获取范围失败: %v", err)
|
||||
}
|
||||
|
||||
expectedCount := 9 // 3行x3列
|
||||
if len(cells) != expectedCount {
|
||||
t.Errorf("范围单元格数量不正确: 期望%d,实际%d", expectedCount, len(cells))
|
||||
}
|
||||
|
||||
// 验证范围内容
|
||||
if cells[0].Row != 1 || cells[0].Col != 0 {
|
||||
t.Errorf("范围起始位置不正确: 期望(1,0),实际(%d,%d)", cells[0].Row, cells[0].Col)
|
||||
}
|
||||
|
||||
lastIndex := len(cells) - 1
|
||||
if cells[lastIndex].Row != 3 || cells[lastIndex].Col != 2 {
|
||||
t.Errorf("范围结束位置不正确: 期望(3,2),实际(%d,%d)",
|
||||
cells[lastIndex].Row, cells[lastIndex].Col)
|
||||
}
|
||||
})
|
||||
|
||||
// 测试7: 查找功能
|
||||
t.Run("单元格查找", func(t *testing.T) {
|
||||
// 查找包含"张"的单元格
|
||||
cells, err := table.FindCellsByText("张", false)
|
||||
if err != nil {
|
||||
t.Errorf("查找失败: %v", err)
|
||||
}
|
||||
|
||||
if len(cells) != 1 {
|
||||
t.Errorf("查找结果数量不正确: 期望1,实际%d", len(cells))
|
||||
}
|
||||
|
||||
if len(cells) > 0 && cells[0].Text != "张三" {
|
||||
t.Errorf("查找内容不正确: 期望'张三',实际'%s'", cells[0].Text)
|
||||
}
|
||||
|
||||
// 精确查找
|
||||
exactCells, err := table.FindCellsByText("25", true)
|
||||
if err != nil {
|
||||
t.Errorf("精确查找失败: %v", err)
|
||||
}
|
||||
|
||||
if len(exactCells) != 1 {
|
||||
t.Errorf("精确查找结果数量不正确: 期望1,实际%d", len(exactCells))
|
||||
}
|
||||
})
|
||||
|
||||
// 测试8: 自定义查找条件
|
||||
t.Run("自定义查找", func(t *testing.T) {
|
||||
// 查找年龄大于26的行
|
||||
ageCells, err := table.FindCells(func(row, col int, cell *document.TableCell, text string) bool {
|
||||
// 检查年龄列(第2列)
|
||||
if col == 1 && row > 0 {
|
||||
// 简单检查是否包含数字且可能大于26
|
||||
return text == "30" || text == "28"
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("自定义查找失败: %v", err)
|
||||
}
|
||||
|
||||
if len(ageCells) != 2 {
|
||||
t.Errorf("自定义查找结果数量不正确: 期望2,实际%d", len(ageCells))
|
||||
}
|
||||
})
|
||||
|
||||
// 保存测试文档
|
||||
outputDir := "../examples/output"
|
||||
if err := os.MkdirAll(outputDir, 0755); err != nil {
|
||||
t.Logf("创建输出目录失败: %v", err)
|
||||
}
|
||||
|
||||
filename := filepath.Join(outputDir, "cell_iterator_integration_test.docx")
|
||||
if err := doc.Save(filename); err != nil {
|
||||
t.Errorf("保存测试文档失败: %v", err)
|
||||
} else {
|
||||
t.Logf("测试文档已保存到: %s", filename)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user