1. 程式人生 > >Oracle”文字”報表輸出

Oracle”文字”報表輸出

Oracle”文字報表輸出

Sam.T

2012-12-12

現象:

一個普通的XML或者PL/SQL過程匯出的Oracle報表,用Excel開啟,第一次存檔的時候,可能很大(之前碰到過,一財務的MMXML報表導2年的資料,文件體積超過50M,而她們的電腦配置低,文件沒法開啟。尷尬。);但是用Excel另存為一個新的Excel文件之後,容量會小很多。為什麼?

就是因為,通常我們看到的文件內容,事實上後面有大量的格式控制程式碼(特別是XML),這些程式碼也會佔用很多容量,導致開啟文件的時候會很慢。當你將這個Excel文件另存之後,Excel會將這些程式碼去掉,所以容量小很多。

XML的格式程式碼見下圖,每個欄位都有:

實現思路:

先說明一下,此方法只適合(大量的)資料匯出。就是對資料的顯示格式沒要求的話可以考慮用這個方法。如果對格式要求很高(例如發貨單/銷售單列印),還是乖乖用XML開發吧,這種一般是單對單的列印,容量大不了哪裡去。

所以現在的目的主要是為了節省輸出的文字字元。通常的包輸出Excel文件的Procedure報表的開發,實際上是開發網頁,一個顯示Excel文件的網頁。眾多的網頁控制程式碼(tr/td等等的網頁格式控制程式碼),佔用了很大空間。別小看這個,如果一個報表要輸出幾十萬行的資料,就是網頁格式控制程式碼都佔用不少空間。同理,XML的也一樣。

所以,基於這個思路,可以考慮直接輸出文字txt

,就是純輸出內容的文字,用製表符TAB按鍵作為欄位的分隔符。主要的步驟還是用FND_FILE.PUT_LINE輸出使用者要的內容,下面有例子。

因為後期是用Excel直接檢視輸出的內容(相當於用Excel開啟txt文字),所以貌似沒出現亂碼等的問題。比較方便。

我自己實際測試過,用這個方法制作的報表匯出的文件的容量,和在Toad裡面直接匯出Excel文件的容量幾乎一樣。

注意地方:

注意的是,如果您的報表的欄位本身就包含製表符,就是說,這個欄位會被自動分行。要特別注意的。可以用RAPLACE的辦法,將欄位內容的TAB符號替代為空或者空格就行。

例子:

--XYG_XXXX公司物料編碼資訊報表

--All Inclusive GUI

PROCEDURE XYG_INV_ITEM_MSG_RPT(

X_ERR_MSG                OUTVARCHAR2

,X_ERR_CODE               OUTNUMBER

,P_ORGANIZATION_ID     INNUMBERDEFAULT107--跑哪個組織下的所有物料。預設是主組織的

,P_ITEM_NUMBER         INVARCHAR2DEFAULTNULL---物料編碼以什麼開頭(因為抓所有的太多)

,P_AUTO_MAIL_RECEIVERINVARCHAR2--發郵件通知的人,不填就是不自動發郵件。填錯當然也發不了

);

PROCEDURE XYG_INV_ITEM_MSG_RPT(

    X_ERR_MSG                OUTVARCHAR2

,X_ERR_CODE               OUTNUMBER

,P_ORGANIZATION_ID     INNUMBERDEFAULT107--跑哪個組織下的所有物料。預設是主組織的

,P_ITEM_NUMBER         INVARCHAR2DEFAULTNULL---物料編碼以什麼開頭(因為抓所有的太多)

,P_AUTO_MAIL_RECEIVER  INVARCHAR2--發郵件通知的人,不填就是不自動發郵件。填錯當然也發不了

)

IS

V_ORGANIZATION_CODE ORG_ORGANIZATION_DEFINITIONS.ORGANIZATION_CODE%TYPE;

V_ORGANIZATION_NAME ORG_ORGANIZATION_DEFINITIONS.ORGANIZATION_NAME%TYPE;

V_MAIL_TITLE  VARCHAR2(1000);

V_MAIL_RECEIVERVARCHAR2(1000);

V_MAIL_CONTENTVARCHAR2(4000);

V_REQUEST_ID  NUMBER;

V_RPT_LINK    VARCHAR2(500);

V_RPT_LINK_CONTENTVARCHAR2(2000);

C_NULL CONSTANTVARCHAR2(10):=null;

CURSOR C_ALL_ITEM

IS

SELECT MSIB.ROWID ROW_ID,MSIB.SEGMENT1 ITEM_NUMBER

,MSIB.DESCRIPTION

,TO_CHAR(MSIB.CREATION_DATE,'YYYY-MM-DD HH24:MI:SS')

CREATION_DATE

,MSIB.PRIMARY_UOM_CODE

FROM MTL_SYSTEM_ITEMS_B MSIB

WHERE1=1--MSIB.ORGANIZATION_ID = OOD.ORGANIZATION_ID

AND MSIB.ENABLED_FLAG='Y'

AND MSIB.INVENTORY_ITEM_STATUS_CODE='Active'

ANDSYSDATEBETWEENNVL(TRUNC(MSIB.START_DATE_ACTIVE),SYSDATE)

ANDNVL(TRUNC(MSIB.END_DATE_ACTIVE),SYSDATE)

AND MSIB.ORGANIZATION_ID= P_ORGANIZATION_ID

AND MSIB.SEGMENT1LIKE P_ITEM_NUMBER ||'%'

ORDERBY2;

----

V_ERROR_LOG_IDNUMBER;

V_PROGRAM_POSITION XYG_PROGRAM_ERROR_LOG.PROGRAM_POSITION%TYPE;

V_ERROR_CODE   XYG_PROGRAM_ERROR_LOG.ERROR_CODE%TYPE;

V_ERROR_MESSAGE XYG_PROGRAM_ERROR_LOG.ERROR_MESSAGE%TYPE;

V_USER_ID      NUMBER:=FND_GLOBAL.USER_ID;

V_LOGIN       NUMBER:=FND_GLOBAL.LOGIN_ID;

BEGIN

V_REQUEST_ID:=FND_GLOBAL.CONC_REQUEST_ID;

-- Output Report Head

LOG('Output Report Head');

OUTPUT ('XYG_XXXXX物料編碼資訊報表');

SELECT ORGANIZATION_CODE,ORGANIZATION_NAME

INTO V_ORGANIZATION_CODE,V_ORGANIZATION_NAME

FROM ORG_ORGANIZATION_DEFINITIONS

WHERE ORGANIZATION_ID= P_ORGANIZATION_ID;

--CHR(9),就是TAB製表符作為欄位的分割。用Excel可以直接開啟。

OUTPUT('編碼組織:'||CHR(9)|| V_ORGANIZATION_CODE||'-'||V_ORGANIZATION_NAME);

OUTPUT ('物料編碼'||CHR(9)||'物料描述'||CHR(9)||'主單位');

FOR RECIN C_ALL_ITEMLOOP

--DBMS_OUTPUT.PUT_LINE(REC.ROW_ID);

OUTPUT(NVL(REC.ITEM_NUMBER, C_NULL)||CHR(9)||NVL(REC.DESCRIPTION, C_NULL)||CHR(9)||NVL(REC.PRIMARY_UOM_CODE, C_NULL));

--DBMS_OUTPUT.PUT_LINE(NVL (REC.ITEM_NUMBER, C_NULL)||CHR(9)||NVL (REC.DESCRIPTION, C_NULL)||CHR(9)||NVL (REC.PRIMARY_UOM_CODE, C_NULL));

--DBMS_OUTPUT.PUT_LINE(LENGTHB(NVL (REC.ITEM_NUMBER, C_NULL))||CHR(9)

--||LENGTHB(NVL (REC.DESCRIPTION, C_NULL))||CHR(9)||LENGTHB(NVL (REC.PRIMARY_UOM_CODE, C_NULL)));

ENDLOOP;

V_PROGRAM_POSITION:='END';

EXCEPTION

WHENFND_API.G_EXC_ERRORTHEN

X_ERR_CODE:=1;

LOG(X_ERR_MSG);

RAISE;

WHENOTHERSTHEN

X_ERR_CODE:=2;

X_ERR_MSG:=SQLERRM;

--NULL;

V_ERROR_CODE:=SQLCODE;

V_ERROR_MESSAGE:=SQLERRM;

LOG(SQLERRM);

RAISE;

DBMS_OUTPUT.PUT_LINE(V_ERROR_CODE ||'-' || V_ERROR_MESSAGE);

END XYG_INV_ITEM_MSG_RPT;

實際執行樣例:

報表註冊: