This commit is contained in:
coco
2026-07-03 16:05:30 +08:00
commit df489d5640
1101 changed files with 779140 additions and 0 deletions
@@ -0,0 +1,251 @@
# 数据导出与导入
<cite>
**本文档引用的文件**
- [ioexpdlg.cpp](file://cpp/Views/ioexpdlg.cpp)
- [ioexpdmsdlg.cpp](file://cpp/Views/ioexpdmsdlg.cpp)
- [ioexpsptdlg.cpp](file://cpp/Views/ioexpsptdlg.cpp)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp)
- [DialMeasureData.cpp](file://cpp/Views/DialMeasureData.cpp)
- [DownloadDataProgressDlg.cpp](file://cpp/Views/DownloadDataProgressDlg.cpp)
- [OperTxtFile.cpp](file://cpp/Tools/OperTxtFile.cpp)
- [OperUrfFile.cpp](file://cpp/Tools/OperUrfFile.cpp)
- [excel.cpp](file://cpp/Tools/excel.cpp)
- [ioexpdlg.h](file://h/ioexpdlg.h)
- [ioexpdmsdlg.h](file://h/ioexpdmsdlg.h)
- [ioexpsptdlg.h](file://h/ioexpsptdlg.h)
</cite>
## 目录
1. [引言](#引言)
2. [数据导出功能架构](#数据导出功能架构)
3. [导出对话框与用户交互](#导出对话框与用户交互)
4. [IOManager协调机制](#iomanager协调机制)
5. [文件操作工具实现](#文件操作工具实现)
6. [导出流程与进度反馈](#导出流程与进度反馈)
7. [用户操作指南](#用户操作指南)
8. [开发者扩展指南](#开发者扩展指南)
9. [结论](#结论)
## 引言
Geomative Studio软件提供了一套完整的数据导出与导入功能,旨在支持地质勘探数据在不同格式间的转换与共享。本系统化文档详细说明了`ioexpdlg``ioexpdmsdlg``ioexpsptdlg`三个核心对话框所支持的导出格式(包括Excel、CSV、TXT、URF)及其底层实现逻辑。文档深入解析了`IOManager`如何作为中央协调者,调用`OperTxtFile``OperUrfFile``excel`等专用文件操作工具来完成复杂的数据转换与文件生成任务。
此外,本文档阐述了从`DialMeasureData`对话框触发的完整导出流程,以及`DownloadDataProgressDlg`提供的实时进度反馈机制。为最终用户提供了关于如何选择导出范围、配置文件命名规则和验证导出完整性的详细操作说明。同时,为开发者提供了关于如何扩展支持新的导出格式(如JSON、PDF)、优化大数据量导出性能的缓冲策略,以及处理文件编码、跨平台换行符等兼容性问题的最佳实践。
**Section sources**
- [ioexpdlg.cpp](file://cpp/Views/ioexpdlg.cpp#L1-L244)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L1-L2064)
## 数据导出功能架构
Geomative Studio的数据导出功能采用分层架构设计,由用户界面层、业务逻辑层和数据访问层协同工作。核心组件`IOManager`位于业务逻辑层,负责协调整个导出流程。当用户通过`DialMeasureData`等界面组件发起导出请求时,控制权会传递给`IOManager`
`IOManager`首先通过`CIOExpDlg`对话框收集用户的导出选项,包括选择要导出的项目、测区和测点数据。随后,它根据用户的选择,调用相应的数据提取和转换逻辑。对于数据库导出,`IOManager`使用ADOX库创建一个新的Access数据库文件(.accdb),并定义其表结构。然后,它将选定的数据从主数据库中提取出来,并插入到新创建的导出文件中。
对于其他格式(如TXT、URF、Excel),`IOManager`会实例化对应的文件操作工具类(如`OperTxtFile``OperUrfFile``excel`),并将数据流传递给它们进行格式化和写入。这种设计实现了关注点分离,使得`IOManager`可以专注于流程控制,而具体的文件格式实现则由专门的工具类负责。
```mermaid
graph TD
A[用户界面] --> B[IOManager]
B --> C[数据提取]
C --> D[格式转换]
D --> E[文件生成]
E --> F[导出文件]
B --> G[OperTxtFile]
B --> H[OperUrfFile]
B --> I[excel]
G --> E
H --> E
I --> E
```
**Diagram sources **
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L35-L98)
- [OperTxtFile.cpp](file://cpp/Tools/OperTxtFile.cpp#L19-L35)
- [OperUrfFile.cpp](file://cpp/Tools/OperUrfFile.cpp#L19-L29)
- [excel.cpp](file://cpp/Tools/excel.cpp#L1-L800)
**Section sources**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L35-L98)
- [OperTxtFile.cpp](file://cpp/Tools/OperTxtFile.cpp#L19-L35)
- [OperUrfFile.cpp](file://cpp/Tools/OperUrfFile.cpp#L19-L29)
- [excel.cpp](file://cpp/Tools/excel.cpp#L1-L800)
## 导出对话框与用户交互
数据导出功能通过一系列对话框与用户进行交互,其中`CIOExpDlg`是主对话框,它整合了`CIOExpDmsDlg``CIOExpSptDlg`两个子对话框,分别用于选择数据(项目、测区、测点)和脚本。
### CIOExpDlg 主对话框
`CIOExpDlg`继承自`CDialog`,其主要职责是提供一个选项卡式界面,让用户在“数据”和“脚本”两个选项卡之间切换。当用户点击“确定”按钮时,该对话框会检查用户是否在任一选项卡中选择了要导出的项目。如果未选择任何项目,会弹出提示框要求用户选择。如果选择了项目,则会弹出文件保存对话框,让用户指定导出文件的路径和名称(默认为.accdb格式)。
```mermaid
classDiagram
class CIOExpDlg {
+CString m_szFileName
+CIOExpDmsDlg m_ioDmsDlg
+CIOExpSptDlg m_ioSptDlg
-INT_PTR* m_pRet
+CIOExpDlg(CWnd* pParent)
+CIOExpDlg(INT_PTR* pRet, CWnd* pParent)
+virtual BOOL Create(UINT nID, CWnd* pParentWnd)
+virtual void OnOK()
+virtual void OnCancel()
+virtual BOOL OnInitDialog()
+afx_msg void OnSelchangeIoExpTab(NMHDR* pNMHDR, LRESULT* pResult)
}
class CIOExpDmsDlg {
+CTreeCtrl m_dmsTree
+CIOExpDmsDlg(CWnd* pParent)
+virtual BOOL OnInitDialog()
+afx_msg void OnShowWindow(BOOL bShow, UINT nStatus)
+afx_msg void OnClickTreeExpDms(NMHDR* pNMHDR, LRESULT* pResult)
+afx_msg void OnSelchangingTreeExpDms(NMHDR* pNMHDR, LRESULT* pResult)
}
class CIOExpSptDlg {
+CListCtrl m_sptList
+CIOExpSptDlg(CWnd* pParent)
+virtual BOOL OnInitDialog()
+afx_msg void OnShowWindow(BOOL bShow, UINT nStatus)
}
CIOExpDlg --> CIOExpDmsDlg : "包含"
CIOExpDlg --> CIOExpSptDlg : "包含"
```
**Diagram sources **
- [ioexpdlg.h](file://h/ioexpdlg.h#L16-L56)
- [ioexpdmsdlg.h](file://h/ioexpdmsdlg.h#L13-L44)
- [ioexpsptdlg.h](file://h/ioexpsptdlg.h#L13-L42)
### CIOExpDmsDlg 数据选择对话框
`CIOExpDmsDlg`使用一个`CTreeCtrl`(树形控件)来展示项目、测区和测点的层级结构。用户可以通过点击树节点旁的复选框来选择要导出的数据。该对话框在初始化时会设置树形控件的样式,使其显示连接线和按钮。`OnClickTreeExpDms`消息处理函数实现了智能的复选框逻辑:当用户选中一个父节点时,其所有子节点也会被自动选中;当用户取消选中一个父节点时,其所有子节点也会被取消选中。
### CIOExpSptDlg 脚本选择对话框
`CIOExpSptDlg`使用一个`CListCtrl`(列表控件)来展示所有可用的脚本。该控件被配置为支持全行选择、拖拽列头、网格线和复选框。在`OnInitDialog`函数中,它会动态地从资源文件中加载列标题(如“脚本编号”、“脚本名称”、“电极数量”等),并创建相应的列。
**Section sources**
- [ioexpdlg.cpp](file://cpp/Views/ioexpdlg.cpp#L1-L244)
- [ioexpdmsdlg.cpp](file://cpp/Views/ioexpdmsdlg.cpp#L1-L145)
- [ioexpsptdlg.cpp](file://cpp/Views/ioexpsptdlg.cpp#L1-L115)
- [ioexpdlg.h](file://h/ioexpdlg.h#L1-L62)
- [ioexpdmsdlg.h](file://h/ioexpdmsdlg.h#L1-L50)
- [ioexpsptdlg.h](file://h/ioexpsptdlg.h#L1-L48)
## IOManager协调机制
`IOManager`是整个数据导出功能的核心协调者。它通过`Export`方法启动导出流程。该方法首先创建并显示`CIOExpDlg`对话框,等待用户完成选择。一旦用户确认,`IOManager`会根据用户选择的文件路径,调用`CreateExpDatabase`方法创建一个新的Access数据库文件,并定义其表结构(如project、tz、td等)。
```mermaid
sequenceDiagram
participant User as 用户
participant CIOExpDlg as CIOExpDlg
participant IOManager as IOManager
participant Database as 数据库
participant File as 文件系统
User->>CIOExpDlg : 点击“导出”
CIOExpDlg->>CIOExpDlg : 显示对话框
User->>CIOExpDlg : 选择数据并点击“确定”
CIOExpDlg->>IOManager : 返回文件路径
IOManager->>IOManager : 创建导出数据库
IOManager->>Database : 提取选定数据
Database-->>IOManager : 返回数据
IOManager->>File : 写入数据到.accdb文件
File-->>IOManager : 写入完成
IOManager-->>User : 显示成功消息
```
**Diagram sources **
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L35-L98)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L206-L656)
**Section sources**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L35-L98)
## 文件操作工具实现
### OperTxtFile 文本文件操作
`OperTxtFile`类负责将数据导出为纯文本(TXT)格式。它提供了一个`SetParamWidth`方法来设置每个字段的宽度,确保导出的文本文件具有整齐的列对齐。`OpenFileforWrite`方法用于打开或创建一个文本文件。`WriteFileContent`方法接收一个`CStringArray`,将数组中的每个字符串按照设定的宽度填充空格后写入文件,不足宽度的部分用空格补齐,每个数组元素写入后会自动添加换行符。
### OperUrfFile URF文件操作
`OperUrfFile`类专门用于生成通用电阻率数据文件(URF)。它支持多种电极阵列类型,如温纳-施伦贝谢(Wenner-Schlumberger)、跨孔(Cross-Hole)等。`WriteElecByAR`方法是核心,它根据传入的阵列类型(iAR)参数,调用不同的私有方法(如`WriteElecByWenSch``WriteElecByCrossHole`)来生成符合特定阵列几何形状的电极坐标。URF文件的头部包含固定的注释和单位信息。
### Excel 文件操作
`excel.cpp`文件包含通过MFC的`COleDispatchDriver`包装类与Microsoft Excel应用程序进行交互的代码。这些包装类(如`_Application``_Workbook``_Worksheet`)允许程序以自动化的方式创建Excel工作簿、写入数据、设置单元格格式等。虽然具体的导出逻辑未在提供的代码片段中完全展示,但可以推断`IOManager`会使用这些类来将数据写入Excel的单元格中,并生成.xlsx或.xls文件。
**Section sources**
- [OperTxtFile.cpp](file://cpp/Tools/OperTxtFile.cpp#L1-L166)
- [OperUrfFile.cpp](file://cpp/Tools/OperUrfFile.cpp#L1-L800)
- [excel.cpp](file://cpp/Tools/excel.cpp#L1-L800)
## 导出流程与进度反馈
### 从DialMeasureData触发导出
数据导出流程通常从`DialMeasureData`对话框开始,该对话框是用户进行测量操作的主要界面。当用户完成测量并希望导出数据时,可以通过菜单或按钮触发导出功能。`DialMeasureData`类本身不直接处理导出,而是通过调用`IOManager``Export`方法来启动整个流程。
### DownloadDataProgressDlg 进度反馈
在执行耗时较长的导出或导入操作时,系统会显示`DownloadDataProgressDlg`对话框来提供进度反馈。该对话框在初始化时会启动一个工作线程(`DownloadThread``UploadThread`),以避免阻塞主UI线程。工作线程会定期调用`ShowProcessPercent`方法,该方法根据已完成的工作量计算百分比,并更新对话框上的进度标签。这确保了用户界面的响应性,并让用户清楚地了解操作的进展情况。
**Section sources**
- [DialMeasureData.cpp](file://cpp/Views/DialMeasureData.cpp#L1-L800)
- [DownloadDataProgressDlg.cpp](file://cpp/Views/DownloadDataProgressDlg.cpp#L1-L479)
## 用户操作指南
### 选择导出范围
1. 在软件主界面,导航到需要导出数据的项目。
2. 右键点击项目、测区或测点,选择“导出”选项。
3. 在弹出的“数据导出”对话框中,切换到“数据”选项卡。
4. 在树形结构中,勾选您想要导出的项目、测区和测点。勾选父节点会自动包含其所有子节点。
5. 切换到“脚本”选项卡,勾选您想要导出的脚本。
### 配置文件命名规则
1. 完成选择后,点击“确定”。
2. 系统会弹出“另存为”对话框。
3. 在“文件名”输入框中,输入您希望的文件名。
4. 系统默认的文件扩展名为`.accdb`,您也可以选择其他格式(如果功能支持)。
5. 选择保存位置,然后点击“保存”。
### 验证导出完整性
1. 导出完成后,系统会显示“导出成功”的提示。
2. 前往您指定的保存位置,找到导出的文件。
3. 打开文件(例如,用Access打开.accdb文件,用文本编辑器打开.txt文件)。
4. 检查文件内容是否与您在导出对话框中选择的数据范围一致,确保所有必要的数据都已包含在内。
## 开发者扩展指南
### 新增导出格式(如JSON、PDF
要支持新的导出格式,开发者需要遵循以下步骤:
1. **创建新的工具类**:创建一个名为`OperJsonFile``OperPdfFile`的新类,类似于`OperTxtFile``OperUrfFile`
2. **实现核心方法**:在新类中实现`OpenFile``WriteData``CloseFile`等核心方法。对于JSON,可以使用第三方库(如nlohmann/json)来构建和序列化JSON对象。对于PDF,可以使用库(如libHaru或PoDoFo)来创建PDF文档并写入表格数据。
3. **扩展IOManager**:在`IOManager`类中添加新的导出方法(如`ExportToJSON``ExportToPDF`),并在`Export`方法中根据用户选择的格式调用相应的方法。
4. **更新用户界面**:在“另存为”对话框的文件类型过滤器中添加新的格式选项(如`JSON Files (*.json)|*.json||`)。
### 优化大数据量导出性能
对于大数据量的导出,应采用缓冲和分块处理策略:
1. **分批读取**:不要一次性将所有数据加载到内存中。使用数据库的分页查询(如`LIMIT``OFFSET`)或游标,分批读取数据。
2. **缓冲写入**:在文件操作工具中,使用缓冲区(buffer)来累积一定量的数据后再写入磁盘,减少I/O操作次数。
3. **异步处理**:将导出操作放在后台线程中执行,避免阻塞UI。`DownloadDataProgressDlg`的实现已经展示了如何使用`AfxBeginThread`来实现这一点。
### 处理兼容性问题
1. **文件编码**:对于文本文件(TXT、CSV),应明确指定编码格式(如UTF-8)。在`OperTxtFile`中,可以修改`fopen`调用,使用`"w+, ccs=UTF-8"`来确保文件以UTF-8编码保存,避免中文乱码。
2. **跨平台换行符**Windows使用`\r\n`,而Unix/Linux使用`\n`。在`OperTxtFile``WriteFileContent`方法中,可以根据目标平台动态选择换行符。可以通过编译宏(如`_WIN32`)来判断当前平台。
## 结论
Geomative Studio的数据导出与导入功能通过清晰的分层架构和模块化设计,实现了高效、可靠的数据交换。`IOManager`作为核心协调者,有效地整合了用户界面、数据访问和文件生成等多个组件。通过分析`ioexpdlg`系列对话框和`OperTxtFile``OperUrfFile`等工具类,我们理解了系统如何支持多种导出格式并提供良好的用户体验。
本文档不仅为用户提供了清晰的操作指南,也为开发者指明了扩展和优化的方向。通过遵循本文档中的最佳实践,可以确保新功能的顺利集成,并持续提升软件在处理复杂地质数据方面的专业性和可靠性。