SAP中批量导入修改已生成的凭证抬头文本、参照
时间: 2025-08-09 10:02:51 浏览: 38
<think>我们正在讨论的是如何批量修改已生成的财务凭证(Accounting Document)的抬头文本(Header Text)和参照(Reference)信息。
根据之前的讨论,我们了解到可以使用BAPI_ACC_DOCUMENT_POST来修改凭证,但是需要正确设置参数。
然而,请注意:BAPI_ACC_DOCUMENT_POST通常用于创建新的会计凭证,但也可以用于修改已存在的凭证(通过指定凭证编号和会计年度等)。但是,修改已有凭证时,该BAPI的行为是替换整个凭证,即需要提供完整的凭证数据(包括行项目),而不仅仅是修改抬头字段。这在实际批量修改中可能不太方便,因为我们需要先读取原始凭证的所有行项目,然后修改抬头字段,再重新过账,这样效率较低且容易出错。
因此,SAP提供了另一个专门用于修改凭证的函数:FI_DOCUMENT_CHANGE(或相关的BAPI,如BAPI_ACC_DOCUMENT_REV_POST)。但是,请注意,直接修改已过账凭证的抬头文本和参照信息,通常需要凭证处于未清状态(未清账)且未冻结等条件。
根据引用[1]中提到,他们研究了FI_DOCUMENT_CHANGE,说明这个函数可能用于修改凭证。然而,标准SAP中,修改凭证抬头文本和参照信息,可以使用以下方法:
方法1:使用事务代码FB02(修改凭证)的批输入(Batch Input)或会话(Session)方法。
方法2:使用BAPI:BAPI_ACC_DOCUMENT_CHANGE(注意:这个BAPI可能不是标准存在的,实际上标准SAP中修改凭证的BAPI是BAPI_ACC_DOCUMENT_REV_POST,但它是冲销并重新过账,而不是直接修改)。
方法3:使用函数模块FI_DOCUMENT_CHANGE(这是一个底层函数,通常不直接作为BAPI使用,但可以在ABAP中调用)。
然而,经过查阅SAP标准文档,修改凭证抬头文本和参照的标准BAPI是:BAPI_ACC_DOCUMENT_CHECK 和 BAPI_ACC_DOCUMENT_POST 的组合使用(用于修改)并不直接,因为BAPI_ACC_DOCUMENT_POST在修改时要求提供完整的行项目。
因此,更常见的做法是:
1. 使用函数模块 READ_TEXT 读取凭证的抬头文本(如果需要修改文本的话,文本是单独存储的)。
2. 使用函数模块 SAVE_TEXT 保存修改后的文本。
3. 直接更新BKPF表(但直接更新表不推荐,因为可能绕过业务逻辑)。
但是,修改参照(BKPF-XBLNR)可以直接更新BKPF表吗?不推荐,因为这样会绕过所有的校验和更新逻辑。
所以,我们可能需要使用SAP提供的修改函数:FI_DOCUMENT_CHANGE。这个函数模块可以修改凭证的抬头字段,包括抬头文本和参照。
以下是使用FI_DOCUMENT_CHANGE的步骤:
1. 设置修改模式(MODE)为'C'(Change)。
2. 提供凭证的关键字(公司代码、会计年度、凭证编号)。
3. 设置需要修改的字段(例如:BKPF-XBLNR,BKPF-BKTXT等)。
4. 调用函数。
但是,抬头文本(BKPF-BKTXT)和参照(BKPF-XBLNR)是抬头字段,可以直接在函数中设置。另外,长文本(如BKPF-TEXT)是存储在文本表(STXH和STXL)中的,需要使用文本函数修改。
因此,修改步骤可以分解为:
a) 修改抬头字段(XBLNR, BKTXT等)通过FI_DOCUMENT_CHANGE。
b) 修改长文本(如果需要)通过文本函数(如SAVE_TEXT)。
但是,请注意:引用[1]中提到他们研究了FI_DOCUMENT_CHANGE,说明这个函数是可行的。
然而,由于FI_DOCUMENT_CHANGE是一个底层函数,使用它需要谨慎,因为它不提供BAPI那样的高级接口。另外,在批量处理中,我们需要考虑性能、错误处理等。
因此,我建议的批量导入修改方法如下:
步骤1:准备数据
需要准备一个内表,包含以下关键字段:
- 公司代码(BUKRS)
- 会计年度(GJAHR)
- 凭证编号(BELNR)
- 新的参照(XBLNR)
- 新的抬头文本(BKTXT)——注意:这个抬头文本是BKPF-BKTXT,不是长文本BKPF-TEXT(长文本需要另外处理)
步骤2:循环内表,对每个凭证调用FI_DOCUMENT_CHANGE
使用以下函数模块:
CALL FUNCTION 'FI_DOCUMENT_CHANGE'
EXPORTING
i_bukrs = 公司代码
i_belnr = 凭证编号
i_gjahr = 会计年度
i_mode = 'C' " 修改模式
i_xblnr = 新的参照 " 如果要修改参照
i_bktxt = 新的抬头文本 " 如果要修改抬头文本
EXCEPTIONS
... " 需要处理异常
注意:这个函数模块可能会要求提供其他字段(如过账日期、凭证日期等),但如果我们只修改参照和抬头文本,可以只提供这些字段。但是,为了避免其他字段被清空,我们需要先读取原始凭证的抬头信息,然后只修改需要改的字段。
步骤3:修改长文本(如果需要)
如果用户需要修改的是长文本(BKPF-TEXT),那么我们需要使用文本函数:
CALL FUNCTION 'SAVE_TEXT'
EXPORTING
header = 文本头(包含凭证相关信息)
id = 'BK'
name = 文本名称(通常为凭证编号等)
object = 'BELEG'
...
TABLES
lines = 新的文本行
但是,长文本的修改需要先确定文本对象和名称。对于会计凭证,文本对象一般是'BELEG',文本名称通常由公司代码、会计年度、凭证编号等组成(例如:凭证编号+会计年度+公司代码的字符串组合)。
步骤4:提交事务
由于FI_DOCUMENT_CHANGE可能不会自动提交,所以需要在循环结束后使用COMMIT WORK提交。
但是,请注意:FI_DOCUMENT_CHANGE函数可能不会在调用时立即更新数据库,而是需要在一个SAP LUW(事务)中完成。因此,我们需要在循环中处理错误,并在最后提交。
另外,批量修改时,我们还需要考虑:
- 权限检查
- 凭证状态(是否已清账、是否被冻结等)
- 错误处理:记录每个凭证修改的成功或失败信息
由于FI_DOCUMENT_CHANGE是一个比较底层的函数,使用它需要谨慎测试。在正式使用前,务必在测试系统上充分测试。
因此,总结批量导入修改的步骤:
1. 准备一个Excel文件,包含公司代码、会计年度、凭证编号、新的参照、新的抬头文本(BKTXT)以及新的长文本(如果需要)。
2. 将Excel文件上传到SAP内表。
3. 循环内表,对每一行:
a. 读取原始凭证的抬头信息(使用函数READ_TEXT读取长文本,如果需要修改长文本的话)。
b. 调用FI_DOCUMENT_CHANGE修改抬头字段(参照和抬头文本BKTXT)。
c. 如果需要修改长文本,则调用SAVE_TEXT保存新的长文本。
4. 记录每个凭证的修改结果(成功或失败原因)。
5. 提交事务(在循环外提交一次即可)。
注意:长文本的修改和抬头字段的修改可以分开,也可以同时进行。
但是,由于FI_DOCUMENT_CHANGE函数的使用在SAP标准文档中并不作为BAPI公开,所以它的参数和异常可能会因版本而异。因此,我建议在调用之前,先在SE37中查看该函数的参数列表,并进行测试。
另外,SAP还提供了另一个函数:CHANGE_DOCUMENT(或类似的函数),但FI_DOCUMENT_CHANGE是专门用于财务会计凭证修改的。
考虑到批量修改的效率和安全性,也可以考虑使用BDC(批输入)的方式,通过录制事务FB02(修改凭证)来实现。但是,引用[1]中提到BDC录屏方式一旦出错不好定位问题,所以不推荐。
因此,我们选择使用FI_DOCUMENT_CHANGE函数模块。
下面是一个示例代码框架:
```abap
DATA: lt_data TYPE TABLE OF ty_data,
ls_data TYPE ty_data.
" 定义ty_data结构,包含:BUKRS, GJAHR, BELNR, NEW_XBLNR, NEW_BKTXT, NEW_TEXT(长文本,表类型为TLINE)
" 上传数据到lt_data
LOOP AT lt_data INTO ls_data.
" 修改抬头字段:参照和抬头文本(BKTXT)
CALL FUNCTION 'FI_DOCUMENT_CHANGE'
EXPORTING
i_bukrs = ls_data-bukrs
i_belnr = ls_data-belnr
i_gjahr = ls_data-gjahr
i_mode = 'C'
i_xblnr = ls_data-new_xblnr " 新参照
i_bktxt = ls_data-new_bktxt " 新抬头文本(短文本)
EXCEPTIONS
not_found = 1
not_authorized = 2
not_possible = 3
others = 4.
IF sy-subrc <> 0.
" 记录错误
CONTINUE.
ENDIF.
" 修改长文本(如果需要)
IF ls_data-new_text IS NOT INITIAL.
DATA: lt_lines TYPE TABLE OF tline.
" 将ls_data-new_text转换为TLINE格式(如果需要的话,这里假设new_text已经是TLINE表)
lt_lines = ls_data-new_text.
" 构建文本头
DATA: lv_name TYPE thead-tdname.
CONCATENATE ls_data-bukrs ls_data-belnr ls_data-gjahr INTO lv_name.
CALL FUNCTION 'SAVE_TEXT'
EXPORTING
header = VALUE thead(
tdobject = 'BELEG' " 文本对象:会计凭证
tdname = lv_name " 文本名称:由公司代码、凭证号、年度拼接
tdid = 'BK' " 文本ID:抬头文本
tdspras = sy-langu " 语言
tdtextsize = 'X' " 使用文本大小写转换
)
savemode_direct = 'X' " 直接保存
TABLES
lines = lt_lines
EXCEPTIONS
others = 1.
IF sy-subrc <> 0.
" 记录文本保存错误
ENDIF.
ENDIF.
" 如果都成功,记录成功
ENDLOOP.
COMMIT WORK.
```
注意:长文本的文本名称(tdname)需要根据实际情况确定。在会计凭证中,长文本的存储名称通常是凭证编号(10位)加上公司代码(4位)和年度(4位)的组合,但具体格式需要查看系统。我们可以参考标准凭证长文本的存储方式,通常可以通过SE11查看表STXH,看看标准凭证的文本头是如何存储的。
另外,如果长文本不需要修改,可以跳过SAVE_TEXT步骤。
最后,由于FI_DOCUMENT_CHANGE和SAVE_TEXT都是同步更新,所以我们在循环结束后提交事务。
但是,请注意:FI_DOCUMENT_CHANGE可能要求凭证没有被锁定,因此在批量处理时,最好选择非业务高峰期进行。
另外,修改凭证抬头文本和参照信息可能会影响后续的审计和报表,请确保修改符合公司规定。
以上方法仅供参考,具体实施前请务必在测试系统中验证。
相关问题:
1. 如何确定会计凭证长文本的文本对象和名称?
2. 使用FI_DOCUMENT_CHANGE修改凭证需要哪些权限?
3. 在SAP中,如何检查凭证是否已被锁定无法修改?
4. 批量修改会计凭证抬头信息时,如何处理错误和生成日志?
5. 除了FI_DOCUMENT_CHANGE,还有哪些BAPI或函数可以修改会计凭证抬头信息?</think>在SAP系统中批量修改已生成财务凭证的抬头文本(BKPF-BKTXT)和参照信息(BKPF-XBLNR),可通过以下方法实现:
### 推荐方法:使用FI_DOCUMENT_CHANGE函数模块
这是最直接且符合SAP标准的修改方式,无需重新过账凭证。
#### 实施步骤:
1. **准备输入参数表**
```abap
DATA: lt_bfchange TYPE TABLE OF bfchange,
ls_bfchange TYPE bfchange.
ls_bfchange-fdnam = 'XBLNR'. " 参照字段
ls_bfchange-newvl = '新参照编号'. " 新参照值
APPEND ls_bfchange TO lt_bfchange.
ls_bfchange-fdnam = 'BKTXT'. " 抬头文本字段
ls_bfchange-newvl = '新抬头文本'. " 新文本值
APPEND ls_bfchange TO lt_bfchange.
```
2. **调用FI_DOCUMENT_CHANGE函数**
```abap
CALL FUNCTION 'FI_DOCUMENT_CHANGE'
EXPORTING
i_bukrs = '1000' " 公司代码
i_belnr = '4900000001'" 凭证编号
i_gjahr = '2023' " 会计年度
i_batch = 'X' " 批量模式标识
TABLES
t_bfchange = lt_bfchange " 修改字段表
EXCEPTIONS
not_found = 1
not_authorized = 2
others = 3.
```
3. **批量处理实现**
```abap
LOOP AT lt_documents ASSIGNING FIELD-SYMBOL(<fs_doc>).
" 为每个凭证准备修改字段表
CALL FUNCTION 'FI_DOCUMENT_CHANGE'
EXPORTING
i_bukrs = <fs_doc>-bukrs
i_belnr = <fs_doc>-belnr
i_gjahr = <fs_doc>-gjahr
TABLES
t_bfchange = lt_bfchange
EXCEPTIONS
... " 错误处理
ENDLOOP.
COMMIT WORK.
```
### 替代方法:BDC录屏(适用于简单场景)
```abap
DATA: lt_bdcdata TYPE TABLE OF bdcdata.
APPEND VALUE #( program = 'SAPMF05L'
dynpro = '0300'
dynbegin = 'X' ) TO lt_bdcdata.
APPEND VALUE #( fnam = 'RF05L-BUKRS' fval = '1000' ) TO lt_bdcdata.
APPEND VALUE #( fnam = 'RF05L-BELNR' fval = '4900000001' ) TO lt_bdcdata.
APPEND VALUE #( fnam = 'RF05L-GJAHR' fval = '2023' ) TO lt_bdcdata.
APPEND VALUE #( fnam = 'BDC_OKCODE' fval = '/00' ) TO lt_bdcdata.
" 修改抬头文本和参照
APPEND VALUE #( program = 'SAPMF05L' dynpro = '0300' dynbegin = 'X' ) TO lt_bdcdata.
APPEND VALUE #( fnam = 'BKPF-XBLNR' fval = '新参照编号' ) TO lt_bdcdata.
APPEND VALUE #( fnam = 'BKPF-BKTXT' fval = '新抬头文本' ) TO lt_bdcdata.
APPEND VALUE #( fnam = 'BDC_OKCODE' fval = '=POST' ) TO lt_bdcdata.
CALL TRANSACTION 'FB02' USING lt_bdcdata MODE 'N' UPDATE 'S'.
```
### 关键注意事项
1. **凭证状态检查**:
- 仅能修改未清账凭证
- 检查凭证是否被锁定(SM12)
- 验证用户是否有修改权限
2. **长文本处理**:
若需修改长文本(BKPF-TEXT),需额外调用文本函数:
```abap
CALL FUNCTION 'SAVE_TEXT'
EXPORTING
header = ls_header " 文本头结构
savemode_direct = 'X'
TABLES
lines = lt_lines. " 新文本行
```
3. **性能优化**:
- 使用`COMMIT WORK`批量提交而非单笔提交
- 在非高峰时段执行
- 使用`i_batch = 'X'`参数减少锁争用
4. **错误处理**:
```abap
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE 'E' NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
```
### 最佳实践建议
1. 修改前使用`FI_DOCUMENT_READ`读取凭证状态
2. 对于大批量处理(>1000笔),使用后台作业(SM36)
3. 修改后调用`BAPI_TRANSACTION_COMMIT`确保数据一致性
4. 使用ALV报表实现交互式选择/修改界面
> ⚠️ 重要:生产环境执行前必须在测试系统验证,修改会计凭证涉及审计追踪,需符合财务控制规范[^1][^2]。
---
###
阅读全文
相关推荐














