Oracle Form 简单实现CSV文件导入功能

转载于 Oracle Form 简单实现CSV文件导入功能 - kiko_0926 - 博客园 (cnblogs.com)

 

功能说明

在FORM界面增加“上传”按钮,点击“上传”按钮,会打开一个窗口,点击“上传文件”按钮,选择模板文件(CSV文件),提交后,后点击“数据验证”按钮,验证文件格式是否正确、验证上传的文件内容是否符合要求或是否正确等,然后点“导入行”按钮,把文件内容导入数据库表中。界面如下:

 实现过程

Step 1:增加窗口Windows

名称:UPLOAD_WIN
子类信息:WINDOW
标题:导入行信息
X轴坐标:0
Y轴坐标:0
宽度:7.677
高度:2.292

Step 2:增加画布Canvas

名称:UPLOAD CAV
画布类型:内容
子类信息:CANVAS
窗口:UPLOAD_WIN
画布上的视图端踹口×轴位置:0
画布上的视图端口Y轴位置:0
宽度:7.677
高度:2.302

Step 3:增加数据块Block

名称:B_UPLOAD
子类信息:BLOCK
导航器样式:同一记录

Step 4:在数据块B_UPLOAD增加数据项Item

“文件名称”文本框:

名称:FILENAME
项类型:文本项
子类信息:TEXT_ITEM_DISPLAY_ONLY
数据类型:Char
数据长度语义:空
最大长度:240
画布:UPLOAD_CAV
X轴坐标:0.74
Y轴坐标:0.219
宽度:5.364
高度:0.25
提示:文件名称

文件ID

名称:FILEID
项类型:文本项
数据类型:Char
数据长度语义:空
最大长度:240

“导入信息”文本框

名称:IMPORT_MSG
项类型:文本项
子类信息:TEXT_ITEM_DISPLAY_ONLY
数据类型:Char
数据长度语义:空
最大长度:2000
画布:UPLOAD_CAV
X轴坐标:0.188
Y轴坐标:0.739
宽度:5.906
高度:1.25
提示:导入消息

数据验证标识

名称:VALIDATE_FLAG
项类型:文本项
数据类型:Char
数据长度语义:空
最大长度:20

 “上传文件”按钮

名称:UPLOAD
项类型:按钮
标签:上传文件
画布:UPLOAD_CAV
X轴坐标:6.416
Y轴坐标:0.167
宽度:0.95
高度:0.3

“数据验证”按钮

名称:VALIDATE
项类型:按钮
标签:数据验证
画布:UPLOAD_CAV
X轴坐标:6.416
Y轴坐标:0.708
宽度:0.95
高度:0.3

 “导入行”按钮

名称:IMPORT
项类型:按钮
标签:导入行
画布:UPLOAD_CAV
X轴坐标:6.416
Y轴坐标:1.674
宽度:0.95
高度:0.3

Step 5:在数据块CONTROL增加“上传”按钮

说明:上传按钮显示在哪个数据块上按需设置,我这里是CONTROL数据块,一般功能按钮放在CONTROL数据块上。
名称:IMPORT
项类型:按钮
标签:导入行
画布:MAIN(CONTROL在画布MAIN上)
(坐标轴位置和按钮大小自己定义)

Step 6:编写“上传”按钮触发器

触发器:WHEN-BUTTON-PRESSED,对象::CONTROL.IMPORT,作用:点击“上传”按钮,打开“导入行信息”窗口
go_block('B_UPLOAD');

Step 7:编写数据操作程序单元

该程序单元主要用来实现上传验证导入等功能。
1.选中对象管理器中的程序单元,点击左边的+,选择程序包规格,在名称中输入B_UPLOAD,确定后,输入如下包头代码:
复制代码
 1 PACKAGE b_upload IS
 2 
 3   --上传文件
 4   PROCEDURE upload;
 5   --数据验证
 6   PROCEDURE validate;
 7   --导入行
 8   PROCEDURE import;
 9 
10 END;
复制代码
2.同1,选择程序包主体,确定后输入包体代码,注意块字段的值的引用格式“:块名.字段名”,具体代码我按功能实现分别显示。

“上传按钮”功能实现代码如下:

复制代码
 1   PROCEDURE upload IS
 2     access_id       NUMBER;
 3     l_server_url    VARCHAR2(200);
 4     l_parameters    VARCHAR2(300);
 5     button_choice   NUMBER;
 6     v_message_level NUMBER;
 7   BEGIN
 8   
 9     --删除该用户导入到接口表数据
10     access_id := fnd_gfm.authorize(NULL);
11     fnd_profile.get('APPS_WEB_AGENT', l_server_url);
12     l_parameters := 'access_id=' || access_id;
13     --打开GFM 文件加载功能,弹出GMF 加载页
14     fnd_function.execute(function_name => 'FND_FNDFLUPL',
15                          open_flag     => 'Y',
16                          session_flag  => 'Y',
17                          other_params  => l_parameters);
18     --文件是否已成功加载?
19     fnd_message.set_name('FND', 'ATCHMT-FILE-UPLOAD-COMPLETE');
20     button_choice := fnd_message.question(button1     => 'YES', --是
21                                           button2     => NULL,
22                                           button3     => 'NO', --否
23                                           default_btn => 1,
24                                           cancel_btn  => 3,
25                                           icon        => 'question');
26     --是
27     IF (button_choice = 1) THEN
28       --文件ID =当前提交的文件ID
29       :b_upload.fileid := fnd_gfm.get_file_id(access_id);
30       --文件ID不为空
31       IF :b_upload.fileid IS NOT NULL THEN
32         --获取文件名称 
33         SELECT file_name
34           INTO :b_upload.filename
35           FROM fnd_lobs
36          WHERE file_id = :b_upload.fileid;
37         --更新文件信息
38         UPDATE fnd_lobs
39            SET expiration_date = SYSDATE + 1
40          WHERE file_id = :b_upload.fileid;
41         v_message_level       := :system.message_level;
42         :system.message_level := 25;
43         COMMIT;
44         :system.message_level := v_message_level;
45       END IF;
46     END IF;
47   
48   END;
复制代码

“数据验证”功能实现代码如下: 

复制代码
 1 PROCEDURE validate IS
 2     l_fileid           NUMBER := to_number(name_in('B_UPLOAD.FILEID'));
 3     l_user_id          NUMBER := fnd_global.user_id;
 4     l_out_msg          VARCHAR2(2000);
 5     l_out_record_count NUMBER;
 6     l_message_level    NUMBER;
 7     l_batch_id         NUMBER;
 8     p_out_msg          VARCHAR2(2000);
 9   
10   BEGIN
11     l_message_level       := :system.message_level;
12     :system.message_level := 25;
13     IF :b_upload.filename IS NULL THEN
14       --获取的文件名称为空报错
15       fnd_message.set_name('CUX', '请先上传文件!');
16       fnd_message.error;
17       go_item('B_UPLOAD.IMPORT');
18       RAISE form_trigger_failure;
19     ELSIF :b_upload.filename NOT LIKE '%.csv' THEN
20       --校验获取的文件格式,按需设置校验
21       fnd_message.set_name('CUX', '导入文件必须为csv格式!');
22       fnd_message.error;
23       go_item('B_UPLOAD.IMPORT');
24       RAISE form_trigger_failure;
25     END IF;
27     --文件信息校验通过,获取导入数据的批号
28     SELECT cux_batch_id_s.nextval INTO l_batch_id FROM dual;
29     :parameter.batch_id := l_batch_id;
30     --读取模板数据到接口表
31     cux_app_pkg.done_data_import(l_batch_id,
32                                  l_fileid,
33                                  :b_upload.filename,
34                                  l_out_record_count,
35                                  l_out_msg);
36   
37     --数据读取到接口表后删除该文件,按需设置
38     DELETE FROM fnd_lobs t WHERE t.file_id = l_fileid;
39     COMMIT;
40     --读取数据过程失败,报错
41     IF l_out_msg IS NOT NULL THEN
42       fnd_message.set_name('CUX', l_out_msg);
43       fnd_message.error;
44       RAISE form_trigger_failure;
45     ELSE
46       --校验上传的文件内容格式等信息是否符合要求
47       cux_validate_pkg.validate_data(l_batch_id, fnd_global.org_id);
48       --返回上传的文件内容验证的行信息
49       cux_app_pkg.validate_imp_data(l_batch_id, p_out_msg);
50       --判断文件信息验证过程报错信息
51       IF p_out_msg IS NULL THEN
52         ---没有报错,判断读取的有效数据行
53         IF l_out_record_count >= 1 THEN
55           --消息提示
56           fnd_message.set_name('CUX', '共读取到' || l_out_record_count || '条数据,数据验证通过!');
59           fnd_message.show;
60           --导入消息显示内容
61           :b_upload.import_msg := '数据验证通过!';
62           --数据验证验证通过,标识为Y
63           :b_upload.validate_flag := 'Y';
64           --导入按钮高亮
65           set_item_property('B_UPLOAD.IMPORT', enabled, property_true);
66         ELSE
67           fnd_message.set_name('CUX', '没有读取到有效数据!');
68           fnd_message.show;
69           :b_upload.import_msg := '没有读取到有效数据!';
70           --没有读取到有效数据,标识为N
71           :b_upload.validate_flag := 'N';
72           --导入按钮显灰
73           set_item_property('B_UPLOAD.IMPORT', enabled, property_false);
74         END IF;
75       ELSE
76         fnd_message.set_name('CUX', '共读取到' || l_out_record_count || '条数据,数据验证不通过!');
78         fnd_message.show;
79         --导入消息显示报错
80         :b_upload.import_msg := p_out_msg;
81         --数据验证验证不通过,标识为N
82         :b_upload.validate_flag := 'N';
83         set_item_property('B_UPLOAD.IMPORT', enabled, property_false);
84       END IF;
86     END IF;
88     :system.message_level := l_message_level;
89   
90   END;
复制代码
其中,batch_id是我自定义的导入批次序列,每次上传均是新的批号,定义如下:
复制代码
1 --创建导入数据的批号序列
2 create sequence CUX_BATCH_ID_S
3 minvalue 1
4 maxvalue 9999999999999999999999999999
5 start with 1
6 increment by 1
7 cache 20;
复制代码
增加参数BATCH_ID:选中对象浏览器中的参数,然后点击左边工具栏上的“+”新增参数,并改名为BATCH_ID,类型改为Number,子类不用设置。我这里将其设置为参数,主要是后面将文件内容导入了数据库表之后,自动查询并显示该批号内容,是否设置为参数,按需定义。
调用的cux_app_pkg程序包规格代码如下:
复制代码
 1 CREATE OR REPLACE PACKAGE cux_app_pkg IS
 2 
 3   --读取模板数据到接口表
 4   PROCEDURE done_data_import(p_batch_id         IN NUMBER,
 5                              p_fileid           IN NUMBER,
 6                              p_file_name        IN VARCHAR2,
 7                              v_out_record_count OUT NUMBER,
 8                              v_out_msg          OUT VARCHAR2);
 9 
10   TYPE conv_varchar2_table IS TABLE OF VARCHAR2(240) INDEX BY BINARY_INTEGER;
11 
12   TYPE error_msg_rec IS RECORD(
13     sno     VARCHAR2(80),
14     err_msg VARCHAR2(300));
15 
16   TYPE error_msg_type IS TABLE OF error_msg_rec INDEX BY BINARY_INTEGER;
17   --导出文件内容
18   PROCEDURE extract_fields(p_src_str    IN VARCHAR2,
19                            p_delimiter  IN VARCHAR2,
20                            p_field_nums IN NUMBER,
21                            p_fields     OUT conv_varchar2_table);
22 
23   --Get blobs from database
24   FUNCTION get_blobs(p_file_id IN NUMBER,
25                      p_blob    OUT BLOB) RETURN BOOLEAN;
26 
27   --Extract strings from blob
28   FUNCTION get_blob_line(p_blob     IN BLOB,
29                          p_line_num IN NUMBER,
30                          p_buf      OUT VARCHAR2) RETURN BOOLEAN;
31 
32   --校验标题列是否正确
33   PROCEDURE validate_file_format(p_buf IN VARCHAR2);
34 
35   --返回上传的文件内容验证的行信息
36   PROCEDURE validate_imp_data(p_batch_id IN NUMBER,
37                               p_out_msg  OUT VARCHAR2);
38 
39 END cux_app_pkg;
复制代码
cux_app_pkg程序包主体代码如下:
复制代码
  1 CREATE OR REPLACE PACKAGE BODY cux_app_pkg IS
  2 
  3   PROCEDURE validate_file_format(p_buf IN VARCHAR2) IS
  4   BEGIN
  5     IF p_buf = '业务实体,组织编码,期间,基数,备注' THEN
  6       NULL;
  7     ELSE
  8       fnd_message.set_name('CUX', '文件格式不正确,请核查!正确标题列应为:业务实体,组织编码,期间,基数,备注');
  9       fnd_message.error;
 10       RAISE form_trigger_failure;
 11     END IF;
 12   
 13   END;
 14 
 15   PROCEDURE extract_fields(p_src_str    IN VARCHAR2,
 16                            p_delimiter  IN VARCHAR2,
 17                            p_field_nums IN NUMBER,
 18                            p_fields     OUT conv_varchar2_table) IS
 19     i             NUMBER;
 20     v_fld         NUMBER;
 21     v_len         NUMBER;
 22     v_str         VARCHAR2(5000);
 23     v_fld_start   BOOLEAN;
 24     v_quote_start BOOLEAN;
 25   BEGIN
 26     -- Test statements here
 27     v_len := nvl(length(p_src_str), 0);
 28     i     := 0; 
 29     --Extract fields
 30     FOR v_fld IN 1 .. p_field_nums
 31     LOOP
 32       --Get new Field
 33       v_fld_start   := TRUE;
 34       v_quote_start := FALSE;
 35       v_str         := ''; 
 36       WHILE i < v_len
 37       LOOP
 38         i := i + 1; 
 39         IF substr(p_src_str, i, 1) = '"' THEN
 40           --Quotation process
 41           IF v_fld_start = TRUE THEN
 42             v_quote_start := TRUE;
 43           ELSIF substr(p_src_str, i + 1, 1) = '"' THEN
 44             v_str := v_str || substr(p_src_str, i, 1);
 45             i     := i + 1; --Move to next
 46           ELSE
 47             v_quote_start := FALSE;
 48           END IF; 
 49           v_fld_start := FALSE;
 50         ELSE
 51           --substr(p_src_str,i+j,1)<>'"'
 52           v_fld_start := FALSE; 
 53           IF v_quote_start = FALSE
 54              AND substr(p_src_str, i, 1) = p_delimiter THEN
 55             --End of field
 56             EXIT;
 57           ELSE
 58             v_str := v_str || substr(p_src_str, i, 1);
 59           END IF;
 60         END IF;
 61       END LOOP; 
 62       p_fields(v_fld) := ltrim(rtrim(v_str));
 63     END LOOP;
 64         
 65   END extract_fields;
 66 
 67   --Get blobs from database
 68   FUNCTION get_blobs(p_file_id IN NUMBER,
 69                      p_blob    OUT BLOB) RETURN BOOLEAN IS
 70   BEGIN
 71     SELECT file_data INTO p_blob FROM fnd_lobs WHERE file_id = p_file_id; 
 72     RETURN TRUE;
 73         
 74   EXCEPTION
 75     WHEN OTHERS THEN
 76       RETURN FALSE;
 77             
 78   END get_blobs;
 79 
 80   --Extract strings from blob
 81   FUNCTION get_blob_line(p_blob     IN BLOB,
 82                          p_line_num IN NUMBER,
 83                          p_buf      OUT VARCHAR2) RETURN BOOLEAN IS
 84     v_len       NUMBER;
 85     v_start_pos NUMBER;
 86     v_end_pos   NUMBER;
 87     v_r_buf     RAW(32767);
 88     v_r_buf_tmp RAW(32767);
 89   BEGIN
 90     p_buf := ''; 
 91     IF p_line_num < 1 THEN
 92       RETURN FALSE;
 93     END IF; 
 94     IF p_line_num = 1 THEN
 95       v_start_pos := 1;
 96     ELSE
 97       v_start_pos := dbms_lob.instr(p_blob,
 98                                     utl_raw.cast_to_raw(chr(10)),
 99                                     1,
100                                     p_line_num - 1) + 1;
101     END IF; 
102     IF (v_start_pos = 1)
103        AND (p_line_num != 1) THEN
104       RETURN FALSE;
105     END IF; --No such Line Number 
106     v_end_pos := dbms_lob.instr(p_blob,
107                                 utl_raw.cast_to_raw(chr(10)),
108                                 1,
109                                 p_line_num);
110   
111     IF v_end_pos = 0 THEN
112       v_end_pos := dbms_lob.getlength(p_blob) + 1;
113     END IF; 
114     v_len := v_end_pos - v_start_pos; 
115     IF v_len > 0 THEN
116       dbms_lob.read(lob_loc => p_blob,
117                     amount  => v_len,
118                     offset  => v_start_pos,
119                     buffer  => v_r_buf);
120       v_r_buf_tmp := utl_raw.convert(v_r_buf,
121                                      'AMERICAN_AMERICA.UTF8',
122                                      'AMERICAN_AMERICA.ZHS16CGB231280'); 
123       IF utl_raw.convert(v_r_buf_tmp,
124                          'AMERICAN_AMERICA.ZHS16CGB231280',
125                          'AMERICAN_AMERICA.UTF8') = v_r_buf THEN
126         v_r_buf := v_r_buf_tmp;
127       END IF; 
128       p_buf := rtrim(utl_raw.cast_to_varchar2(v_r_buf), chr(13));
129     END IF; 
130     RETURN TRUE;
131         
132   END get_blob_line;
133 
134   PROCEDURE done_data_import(p_batch_id         IN NUMBER,
135                              p_fileid           IN NUMBER,
136                              p_file_name        IN VARCHAR2,
137                              v_out_record_count OUT NUMBER,
138                              v_out_msg          OUT VARCHAR2) IS
139     l_read_count    NUMBER := 0;
140     l_succeed_count NUMBER := 0;
141     l_failed_count  NUMBER := 0;
142     v_delim         VARCHAR2(10) := ','; --CSV文件列值之间用,分隔
143     v_tmp_str       VARCHAR2(1000);
144     v_blob          BLOB;
145     v_line_buf      VARCHAR2(30000);
146     v_fld_nums      NUMBER := 5; --列数
147     v_fields        conv_varchar2_table;
148     l_erros_msg     error_msg_type;
149     v_skip_line     NUMBER := 1;
150     v_line_id       NUMBER;
151     rec_demand_imp  cux_import_interface%ROWTYPE;
152   
153   BEGIN
154     IF get_blobs(p_fileid, v_blob) != TRUE THEN
155       --清空导入消息字段值
156       :b_upload.import_msg := NULL;
157       --报错
158       fnd_message.setname('CUX', '不存在文件ID : ' || p_fileid || ',请重新上传文件! ');
159       fnd_message.error;
160       RAISE form_trigger_failure;
161     ELSE
162       --获取文件名
163       SELECT MAX(file_name)
164         INTO v_tmp_str
165         FROM fnd_lobs
166        WHERE file_id = p_fileid;
167       --清空报错消息记录
168       l_erros_msg.delete;
169       l_read_count    := 0;
170       l_failed_count  := 0;
171       l_succeed_count := 0;
172       v_line_id       := 1;
173       --读取文件行信息
174       WHILE get_blob_line(v_blob, l_read_count + 1, v_line_buf)
175       LOOP
176         BEGIN
177         
178           rec_demand_imp := NULL;
179           l_read_count   := l_read_count + 1;
180           IF v_line_buf IS NOT NULL THEN
181             --因为我这里CSV文件列为5个字段,故是4个,分隔符,这里表示读取到空白行,停止读取
182             IF v_line_buf = ',,,,' THEN
183               EXIT;
184             END IF;
185             --导出文件内容
186             extract_fields(v_line_buf, v_delim, v_fld_nums, v_fields);
187             --读取到第一行为标题列 
188             IF l_read_count = v_skip_line THEN
189               --校验标题列是否正确
190               validate_file_format(v_line_buf);
191             END IF;
192             --从第2行开始为内容信息
193             BEGIN
194               IF l_read_count > v_skip_line THEN
195                 rec_demand_imp.file_name         := :b_upload.filename;
196                 rec_demand_imp.batch_id          := p_batch_id;
197                 rec_demand_imp.org_id            := fnd_global.org_id;
198                 rec_demand_imp.company_code      := v_fields(1);
199                 rec_demand_imp.org_code          := v_fields(2);
200                 rec_demand_imp.period_name       := v_fields(3);
201                 rec_demand_imp.base_amount       := v_fields(4);
202                 rec_demand_imp.comments          := v_fields(5);
203                 rec_demand_imp.created_by        := fnd_global.user_id;
204                 rec_demand_imp.last_updated_by   := fnd_global.user_id;
205                 rec_demand_imp.creation_date     := SYSDATE;
206                 rec_demand_imp.last_update_date  := SYSDATE;
207                 rec_demand_imp.last_update_login := fnd_global.login_id;
208                 --插入到接口表
209                 INSERT INTO cux_import_interface VALUES (rec_demand_imp);
210                 COMMIT;
211                 v_line_id := v_line_id + 1;
212               END IF;
213             EXCEPTION
214               WHEN OTHERS THEN
215                 v_out_msg            := SQLERRM || ',INSERT INTO CUX_IMPORT_INTERFACE错误!';
216                 :b_upload.import_msg := NULL;
217             END;
218           
219           ELSE
220             EXIT;
221           END IF;
222         END;
223       END LOOP;
224       v_out_record_count := l_read_count - 2;
225     END IF;
226   EXCEPTION
227     WHEN OTHERS THEN
228       v_out_msg            := '读取模板文件错误:' || SQLERRM;
229       :b_upload.import_msg := NULL;
230   END;
231 
232   PROCEDURE validate_imp_data(p_batch_id IN NUMBER,
233                               p_out_msg  OUT VARCHAR2) IS
234   
235     CURSOR cur_error IS
236       SELECT *
237         FROM cux.cux_import_interface t
238        WHERE t.batch_id = p_batch_id
239          AND t.validated_flag = 'E';
240   
241   BEGIN
242     FOR c1 IN cur_error
243     LOOP
244       --消息提示错误行内容
245       p_out_msg := substrb('行' || c1.company_code || ';' || c1.org_code || ';' ||
246                            c1.period_name || ';' || c1.base_amount || ';' ||
247                            c1.comments || '错误信息:' || c1.data_error ||
248                            chr(10) || chr(13) || p_out_msg,
249                            1,
250                            10000);
251     
252     END LOOP;
253   EXCEPTION
254     WHEN OTHERS THEN
255       NULL;
256   END;
257 
258 END;
复制代码
调用的cux_validate_pkg.validate_data存储过程主要是实现从接口表cux_import_interface获取该批号数据,在导入到业务表或正式表前对数据进行一系列验证,根据需要自己编写代码进行验证,此处不再赘述。
接口表CUX_IMPORT_INTERFACE:
复制代码
 1 create table CUX_IMPORT_INTERFACE
 2 (
 3   file_name          VARCHAR2(250) not null,
 4   batch_id           NUMBER not null,
 5   org_id             NUMBER,
 6   company_code       VARCHAR2(50),
 7   org_code           VARCHAR2(20),
 8   period_name        VARCHAR2(20),
 9   base_amount        NUMBER,
10   comments           VARCHAR2(250),
11   validated_flag     VARCHAR2(1) default 'N',
12   data_error         VARCHAR2(250),
13   creation_date      DATE default sysdate,
14   created_by         NUMBER default -1,
15   last_update_date   DATE default sysdate,
16   last_updated_by    NUMBER default -1,
17   last_update_login  NUMBER default -1,
18   attribute_category VARCHAR2(20),
19   attribute1         VARCHAR2(250),
20   attribute2         VARCHAR2(250),
21   attribute3         VARCHAR2(250),
22   attribute4         VARCHAR2(250),
23   attribute5         VARCHAR2(250)
24 )
25 tablespace APPS_TS_TX_DATA
26   pctfree 10
27   initrans 1
28   maxtrans 255
29   storage
30   (
31     initial 128K
32     next 8K
33     minextents 1
34     maxextents unlimited
35     pctincrease 0
36   );
复制代码

“导入行”功能实现代码如下:

复制代码
 1 PROCEDURE import IS
 2     v_message_level NUMBER;
 3     v_out_msg       VARCHAR2(1000);
 4   BEGIN
 5     v_message_level       := :system.message_level;
 6     :system.message_level := 25;
 7     --获取的文件名称不为空
 8     IF :b_upload.filename IS NOT NULL THEN
 9       --数据验证标识为Y,将文件内容导入数据库表
10       IF :b_upload.validate_flag = 'Y' THEN
11         IF v_out_msg IS NULL THEN
12           --把该数据批号导入数据库表
13           cux_validate_pkg.import_data(:parameter.batch_id, v_out_msg);
14           COMMIT;
15           --导入过程报错
16           IF v_out_msg IS NOT NULL THEN
17             --显示错误消息
18             fnd_message.set_name('CUX', '提交请求失败!' || v_out_msg);
19             fnd_message.show;
20             RETURN;
21           ELSE
22             --否则,显示成功消息
23             fnd_message.set_name('CUX', '文件信息行导入成功完成!');
24             fnd_message.show;
25           END IF;
26           --清空对应字段值
27           :b_upload.filename   := NULL;
28           :b_upload.fileid     := NULL;
29           :b_upload.import_msg := NULL;
30           --数据验证标识设置为N
31           :b_upload.validate_flag := 'N';
32         ELSE
33           --提示报错消息
34           fnd_message.set_name('CUX', v_out_msg);
35           fnd_message.show;
36         END IF;
37       ELSE
38         --数据验证标识为N,提示消息
39         fnd_message.set_name('CUX', '文件数据必须验证通过后才能导入');
40         fnd_message.show;
41       END IF;
42     ELSE
43       --获取的文件名称为空提示消息
44       fnd_message.set_name('CUX', '导入文件不能为空!');
45       fnd_message.show;
46     END IF;
47     COMMIT;
48     :system.message_level := v_message_level;
49     --自动查询并显示该数据批号的信息
50     go_block('FOLDER');
51     set_block_property('FOLDER',
52                        default_where,
53                        'where batch_id =' || :parameter.batch_id);
54     do_key('EXECUTE_QUERY');
55   
56   END;
复制代码

调用的cux_validate_pkg.import_data存储过程主要是实现从接口表cux_import_interface获取该批号数据,数据校验通过插入到业务表或正式表,根据需要自己编写代码,此处也不再赘述。

Step 8:编写“上传文件”按钮触发器

触发器:WHEN-BUTTON-PRESSED,对象::B_UPLOAD.UPLOAD,作用:调用上传文件功能
b_upload.upload;

Step 9:编写“数据验证”按钮触发器

触发器:WHEN-BUTTON-PRESSED,对象::B_UPLOAD.VALIDATE,作用:调用数据验证功能,导入到接口表后进行数据验证。
b_upload.validate;

Step 10:编写“导入行”按钮触发器

触发器:WHEN-BUTTON-PRESSED,对象::B_UPLOAD.IMPORT,作用:调用导入功能,数据验证通过后导入到业务表。
b_upload.import;
 到此,基本实现利用CSV文件批量导入数据的功能。
 
 
 
其他
 

业务背景
在我之前发表的一篇文章《Oracle EBS使用CSV导入Oracle Form及BOM清单导入 API》提到上传导入数据的文件,同时也可以用于文件上传和下载。

Oracle EBS标准上传和下载
上传代码:

/**上传文件
返回值: 上传文件的标识:FND_LOBS.FILE_ID
*/
Function UploadFile Return Number Is
l_AccessId Number;
l_ServerUrl Varchar2(20000);
l_Url Varchar2(20000);
l_ButtonChoice Number;
l_FileId Number;
l_OracleCharset Varchar2(30);
Begin
--Get Process ID
l_AccessId := Fnd_Gfm.authorize(Null);
--Get Web Page
Fnd_Profile.Get('APPS_WEB_AGENT', l_ServerUrl);

l_Url := Rtrim(l_ServerUrl, '/') ||
'/fnd_file_upload.displayGFMform?access_id=' ||
To_Char(l_AccessId) || Chr(38) || 'l_server_url=' || l_ServerUrl;

If (l_Url Is Null) Then
Fnd_Message.Set_String('调用Url失败!');
Fnd_Message.Show;
Raise Form_Trigger_Failure;
End If;
--Open Web Page
Fnd_Utilities.Open_Url(l_Url);
Fnd_Message.Set_String('请选择在打开网页导入的文件,单击“是”按钮上传完毕! ');
l_ButtonChoice := Fnd_Message.Question(button1 => 'Yes',
button2 => null,
button3 => 'No',
default_btn => 1,
cancel_btn => 3,
icon => 'Question');
--Get File ID
l_FileId := Fnd_Gfm.Get_File_ID(l_AccessId);
--获得客户端字符集
If l_FileId Is Not Null And l_FileId <> 0 Then
Select oracle_charset
Into l_OracleCharset
From FND_LOBS
Where FILE_ID = l_FileId;
:Parameter.CLIENTCHARSET := Substr(:Parameter.CLIENTCHARSET,
1,
Instr(:Parameter.CLIENTCHARSET, '.')) ||
l_OracleCharset;
End If;
--取消上传将要删除上传文件的记录
If (l_ButtonChoice = 3) Then
Begin
Delete From FND_LOBS Where FILE_ID = l_FileId;
Exception
When No_Data_Found Then
Null;
End;
l_FileId := 0;
Forms_Ddl('commit');
End If;
Return l_FileId;
End;
其实,调用Oracle EBS标准API上传文件,被上传的文件保存在FND_LOBS表字段FILE_DATA中。

下载代码
参考代码如下:

DECLARE
l_FileId Number;
l_DownloadUrl Varchar2(2000);
BEGIN
--文件标识,来源于FND_LOBS.FILE_ID
l_FileId := :CONTROL.FILE_ID;
--获得下载URL
l_DownloadUrl := fnd_gfm.construct_download_url(fnd_web_config.gfm_agent,
l_FileId,
TRUE);
--下载文件
fnd_utilities.open_url(l_DownloadUrl);
END;
默认下载保存的文件名为:fnd_gfm.zip,需要自己行修改文件名称和文件类型。

优缺点:
优点:
调用Oracle EBS标准功能编写代码工作量小,简单快捷。比较合适处理批量数据导入。
缺点:
1.由于文件存放在Oracle EBS标准FND_LOBS表中,不合适上传数量多和单个大文件,比如:物料图片和技术图纸。
下载文件名称统一默认为fnd_gfm.zip,不便用户使用。
————————————————
版权声明:本文为CSDN博主「AlanChen」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/chenxianping/article/details/81166402

posted @ 2023-02-20 10:49  shu'sblog  阅读(227)  评论(0编辑  收藏  举报