首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

用 Visual C++ 增強 Lotus Notes 打印功能:動態構造表單實現多版式輸出

     編輯:VC 教學

背景與痛點

Lotus Domino/Notes 廣泛用於辦公自動化,但打印功能極弱:文檔只能按給定表單版式打印。實際中(如政府公文),同一內容需上行/下行不同版式。修改表單受限於隱藏設計,最終用戶技術有限無法操作。

解決方案:VC++ 構建「所見即所得」編輯器

  • 提供可視化編輯界面,列出 Notes 文檔各部分內容。
  • 用戶拖放方式排版,可添加文字、圖片修飾。
  • 按最終版式在 Notes 外部動態生成表單並打印。
  • 繞過隱藏設計限制,降低用戶技術門檻。核心依賴 Notes C API。

一、Notes 表單結構核心域解析

表單 Note 必含三域:$TITLE、$INFO、$BODY;輔助域:$FIELDS、placeholder 域。

1. $TITLE 域

  • 類型 TYPE_TEXT,存表單名稱(客戶端「創建」菜單顯示的名稱)。
  • API 常量 ITEM_NAME_TEMPLATE_NAME 代表此域,建議用常量保兼容性。

2. $INFO 域

  • 類型 TYPE_COMPOSITE,存 CDDOCUMENT 結構體,定義通過此表單創建文檔的屬性。
  • 常量 ITEM_NAME_DOCUMENT。結構體定義詳見 Lotus C API 參考。

3. $BODY 域(核心)

  • 類型 TYPE_COMPOSITE,常量 ITEM_NAME_TEMPLATE。
  • 定義整個表單顯示/打印格式、生成文檔包含的域及類型。
  • 結構極其複雜,由多種 CD* 結構體組成(CDTEXT、CDFIELD、CDPABDEFINITION 等)。

4. $FIELDS 域

  • TYPE_TEXT_LIST,列出生成文檔包含的所有域名。純打印表單可無此域。

5. Placeholder 域

  • 類型 TYPE_INVALID_OR_UNKNOWN,標志 ITEM_PLACEHOLDER,域名同 $BODY 定義,值為 NULL。
  • 加入「域名表」,使設計菜單「添加域」對話框可見。打印表單非必需。

二、$BODY 域詳細結構

整體結構示例:

CDPABDEFINITION
CDPABDEFINITION
...
CDPARAGRAPH
CDPABREFERENCE
CDTEXT
text
...
CDPARAGRAPH
CDPABREFERENCE
CDBEGINRECORD
CDFIELD
CDBEGINRECORD
...

1. 段落預定義部分

CDPABDEFINITION 定義段落屬性:對齊、頁邊距、段間距、行間距等。PABID 序號唯一即可,位置靈活。

2. 靜態文本定義

  • CDPARAGRAPH:段落開始(類似換行)。
  • CDPABREFERENCE:引用段落定義(PABID)。
  • CDTEXT:文本頭部,含長度、字體、顏色。
  • text:實際文本內容。

3. 域定義

  • 同樣以 CDPARAGRAPH + CDPABREFERENCE 開始。
  • 域等對象需 CDBEGINRECORD/CDENDRECORD 包裹前後。
  • 提示性文字(如「姓名:」)置於 CDBEGINRECORD 前,作文本處理。
  • 貨幣/數值域需插入 CDEXT2FIELD 提供附加格式。
  • 默認值公式、輸入轉換公式、域名、描述等置於 CDFIELD 後,順序與長度值在結構體中一致。除域名外可省略。

三、通過 API 創建 Notes 表單

  1. 打開數據庫,創建空白 Note。
  2. 單一類型域($TITLE)用 NSFItemSetText 創建。
  3. 復合類型域($INFO、$BODY):
    1. 申請大塊內存(OSMemAlloc)。
    2. 順序寫入各部分:字符串直接寫,結構體用 ODSWriteMemory 以 Domino 規範寫入,公式經 NSFFormulaCompile 編譯後寫入。
    3. 調用 NSFItemAppend 創建域。

四、實例代碼:創建帶默認值公式的文本域


// 定義域屬性
char TextFieldName[] = "TextField";
char TextDescription[] = "This is a Simple Text Field";
char TextDefValFormula[] = "\"Default\"";

char far *pBufferStart, far *pBuffer;
HANDLE hMem;
CDPABREFERENCE CDPabRef; 
CDPARAGRAPH CDPara;
CDBEGINRECORD CDBegin;
CDENDRECORD CDEnd;
CDEXT2FIELD CDExt2Field;
CDFIELD CDField;
FONTIDFIELDS *pFontFields;

// 申請並鎖定內存
OSMemAlloc(0, wCDBufferLength, &hMem);
pBufferStart = (char far *)OSLockObject(hMem);
memset(pBufferStart, 0, (size_t)wCDBufferLength);
pBuffer = pBufferStart;

// 填寫 PARAGRAPH
CDPara.Header.Length = (BYTE)ODSLength(_CDPARAGRAPH);
CDPara.Header.Signature = (BYTE)SIG_CD_PARAGRAPH;
ODSWriteMemory((void far * far *)&pBuffer, _CDPARAGRAPH, &CDPara, 1);

// 填寫 PABREFERENCE
CDPabRef.Header.Signature = (BYTE)SIG_CD_PABREFERENCE;
CDPabRef.Header.Length = (BYTE)ODSLength(_CDPABREFERENCE);
CDPabRef.PABID = wPabDefNumber; // 引用的段定義序號
ODSWriteMemory((void far * far *)&pBuffer, _CDPABREFERENCE, &CDPabRef, 1);

// 填寫 CDBEGINRECORD
CDBegin.Header.Length = (BYTE)ODSLength(_CDBEGINRECORD);
CDBegin.Header.Signature = SIG_CD_BEGIN;
CDBegin.Version = 0;
CDBegin.Signature = SIG_CD_FIELD;
ODSWriteMemory((void far * far *)&pBuffer, _CDBEGINRECORD, (void far *)&CDBegin, 1);

// 填寫 CDEXT2FIELD
memset(&CDExt2Field, 0, sizeof(CDEXT2FIELD));
CDExt2Field.Header.Length = (WORD)ODSLength(_CDEXT2FIELD);
CDExt2Field.Header.Signature = SIG_CD_EXT2_FIELD;
ODSWriteMemory((void far * far *)&pBuffer, _CDEXT2FIELD, (void far *)&CDExt2Field, 1);

// 填寫 CDFIELD 核心部分
CDField.Header.Signature = SIG_CD_FIELD;
CDField.Flags = FEDITABLE;
CDField.DataType = TYPE_TEXT;
CDField.ListDelim = LDDELIM_SEMICOLON;
// 數值/時間格式參數清零 ...
// 設置 FontID
pFontFields = (FONTIDFIELDS *)&CDField.FontID;
pFontFields->Face = FONT_FACE_ROMAN;
pFontFields->Attrib = 0;
pFontFields->Color = NOTES_COLOR_BLACK;
pFontFields->PointSize = 14;

// 編譯默認值公式
NSFFormulaCompile(NULL, 0, TextDefValFormula, (WORD)strlen(TextDefValFormula),
    &hTextDefValFormula, &wTextDefValFormulaLen, &wdc, &wdc, &wdc, &wdc, &wdc);

// 填寫 CDFIELD 剩餘長度字段
CDField.DVLength = wTextDefValFormulaLen;
CDField.ITLength = 0; CDField.TabOrder = 0; CDField.IVLength = 0;
CDField.NameLength = strlen(TextFieldName);
CDField.DescLength = strlen(TextDescription);
CDField.TextValueLength = 0;
CDField.Header.Length = ODSLength(_CDFIELD) + CDField.DVLength + CDField.ITLength
    + CDField.IVLength + CDField.NameLength + CDField.DescLength + CDField.TextValueLength;
if (CDField.Header.Length % 2) CDField.Header.Length++; // 確保偶數長度
ODSWriteMemory((void far * far *)&pBuffer, _CDFIELD, (void far *)&CDField, 1);

// 寫入公式內容
pTextDefValFormula = OSLock(char, hTextDefValFormula);
memcpy(pBuffer, pTextDefValFormula, wTextDefValFormulaLen);
pBuffer += CDField.DVLength;
OSUnlockObject(hTextDefValFormula); OSMemFree(hTextDefValFormula);

// 寫入域名與描述
memcpy(pBuffer, TextFieldName, CDField.NameLength); pBuffer += CDField.NameLength;
memcpy(pBuffer, TextDescription, CDField.DescLength); pBuffer += CDField.DescLength;

// 確保整體偶數長度
if ((pBuffer - pBufferStart) % 2) pBuffer++;

// 填寫 CDENDRECORD
CDEnd.Header.Length = (BYTE)ODSLength(_CDENDRECORD);
CDEnd.Header.Signature = SIG_CD_END;
CDEnd.Version = 0; CDEnd.Signature = SIG_CD_FIELD;
ODSWriteMemory((void far * far *)&pBuffer, _CDENDRECORD, (void far *)&CDEnd, 1);

關鍵技術點總結

  • 內存管理: OSMemAlloc/Lock/Unlock/Free 管理遠指針內存。
  • 規範寫入: 結構體必須用 ODSWriteMemory 以 Domino 標準格式寫入(字節序、對齊)。
  • 公式編譯: 公式字符串需 NSFFormulaCompile 編譯為字節碼再寫入。
  • 長度計算: 所有長度字段必須精確,結構體長度含可變部分,且通常要求偶數對齊。

掌握此技術,可實現 Notes 文檔的任意版式動態生成與打印,極大增強應用靈活性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved