各位前輩好,想請教一個問題,因公司專案跟政府部門配合
而公文列印出來的編號清單都需要用中文顯示
目前功能是在網頁上輸入文字,再列印成pdf檔
上圖是使用Telerik的html編輯器產生的,list-style-type是使用css提供的
cjk-ideographic中文字形,而列印成pdf檔用的是itextsharp
比如說 下圖是目前list的呈現方式
在itext官方文件上面,只有看到GreekList, RomanList, ZapfDingbatsList, ZapfDingbatsNumberList 四種特殊List
想請問itextsharp生成PDF有沒有中文list的呈現方式? 謝謝各位
問題解決 謝謝 fysh711426 大大
附上相關程式碼
namespace iTextSharp.Extensions
{
public class ChineseList : List
{
public ChineseList(bool brackets, bool IsoldNumber)
{
this.numbered = IsoldNumber; //true= 甲乙丙丁,false=一二三四
this.lowercase = brackets; //true = 、 ,false = () ;
}
public override bool Add(IElement o)
{
string postSymbol1 = "、";
string postSymbol2 = "(";
string postSymbol3 = ")";
if (o is ListItem)
{
ListItem item = (ListItem)o;
Chunk chunk = new Chunk(preSymbol, symbol.Font);
if (lowercase) //加頓號
{
chunk.Attributes = symbol.Attributes;
chunk.Append(ChineseNumberFactory.GetString(first + list.Count, numbered));
chunk.Append(postSymbol1);
}
else //加括號
{
chunk.Attributes = symbol.Attributes;
chunk.Append(postSymbol2);
chunk.Append(ChineseNumberFactory.GetString(first + list.Count, numbered));
chunk.Append(postSymbol3);
}
item.ListSymbol = chunk;
item.SetIndentationLeft(symbolIndent, autoindent);
item.IndentationRight = 0;
list.Add(item);
return true;
}
else if (o is List)
{
List nested = (List)o;
nested.IndentationLeft = nested.IndentationLeft + symbolIndent;
first--;
list.Add(nested);
return true;
}
return false;
}
}
public class ChineseNumberFactory
{
public static string GetString(int index, bool IsOldNumber)
{
return FormatChineseNumber(index, IsOldNumber);
}
private static string FormatChineseNumber(decimal n, bool IsOldNumber) //轉換為中文數字
{
string t =
EastAsiaNumericFormatter.FormatWithCulture(
"Ln", n,
null, new CultureInfo("zh-TW"));
if (IsOldNumber)
{
string o = GetChineseOldNumber(n);
return o;
}
string pattern = "[^一二三四五六七八九]十";
string one = "一";
string res = Regex.Replace(t, pattern, m =>
{
return m.Value.Substring(0, 1) + one + m.Value.Substring(1);
});
return res;
}
private static string GetChineseOldNumber(decimal n) //轉換為中國數字
{
string[] strChineseOldNumber = { "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸" };
n = n - 1;
string NewStr = n.ToString();
int len = NewStr.Length;
string tmpstr, rstr;
rstr = "";
for (int i = 1; i <= len; i++)
{
tmpstr = NewStr.Substring(len - i, 1);
rstr = rstr + strChineseOldNumber[Int32.Parse(tmpstr)];
}
return rstr;
}
}
public class NumberList : List //數字加上頓號、括號
{
public NumberList(bool lowercase)
: base(true)
{
this.lowercase = lowercase;
}
public override bool Add(IElement o)
{
string postSymbol1 = "、";
string postSymbol2 = "(";
string postSymbol3 = ")";
if (o is ListItem)
{
ListItem item = (ListItem)o;
Chunk chunk = new Chunk(preSymbol, symbol.Font);
int index =first + list.Count;
if (lowercase) //加頓號
{
chunk.Attributes = symbol.Attributes;
chunk.Append(index.ToString());
chunk.Append(postSymbol1);
}
else //加括號
{
chunk.Attributes = symbol.Attributes;
chunk.Append(postSymbol2);
chunk.Append(index.ToString());
chunk.Append(postSymbol3);
}
item.ListSymbol = chunk;
item.SetIndentationLeft(symbolIndent, autoindent);
item.IndentationRight = 0;
list.Add(item);
return true;
}
else if (o is List)
{
List nested = (List)o;
nested.IndentationLeft = nested.IndentationLeft + symbolIndent;
first--;
list.Add(nested);
return true;
}
return false;
}
}
}
測試結果:
研究了一下,給大大參考看看。
剛剛跑去 GitHub 偷看了 RomanList.cs 的程式碼,
感覺可以改成中文的,所以試了一下。
namespace iTextSharp.Extensions
{
public class ChineseList : List
{
public ChineseList() : base(true)
{
this.lowercase = true;
}
public ChineseList(int symbolIndent) : base(true, symbolIndent)
{
this.lowercase = true;
}
public ChineseList(bool lowercase) : base(true)
{
this.lowercase = lowercase;
}
public ChineseList(bool lowercase, int symbolIndent) : base(true, symbolIndent) {
this.lowercase = lowercase;
}
public override bool Add(IElement o)
{
if (o is ListItem)
{
ListItem item = (ListItem)o;
Chunk chunk = new Chunk(preSymbol, symbol.Font);
chunk.Attributes = symbol.Attributes;
chunk.Append(ChineseNumberFactory.GetString(first + list.Count, lowercase));
chunk.Append(postSymbol);
item.ListSymbol = chunk;
item.SetIndentationLeft(symbolIndent, autoindent);
item.IndentationRight = 0;
list.Add(item);
return true;
}
else if (o is List)
{
List nested = (List)o;
nested.IndentationLeft = nested.IndentationLeft + symbolIndent;
first--;
list.Add(nested);
return true;
}
return false;
}
}
public class ChineseNumberFactory
{
public static string GetString(int index, bool lowercase)
{
return FormatChineseNumber(index, !lowercase);
}
private static string FormatChineseNumber(decimal n, bool moneyChar)
{
string t =
EastAsiaNumericFormatter.FormatWithCulture(
moneyChar ? "L" : "Ln", n,
null, new CultureInfo("zh-TW"));
string pattern = moneyChar ?
"[^壹貳參肆伍陸柒捌玖]拾" :
"[^一二三四五六七八九]十";
string one = moneyChar ? "壹" : "一";
string res = Regex.Replace(t, pattern, m =>
{
return m.Value.Substring(0, 1) + one + m.Value.Substring(1);
});
if (moneyChar && res.StartsWith("拾"))
{
res = "壹" + res;
}
return res;
}
}
}
數字轉換參考了黑暗大大的這篇文章,可以支援一般一二三
和金額壹貳參
。
CODE-將地址中的阿拉伯數字轉為中文大寫
安裝 InternationalNumericFormatter.dll 參考了小歐大大的這篇文章。
[C#]Visual Studio International Feature Pack 2.0 與阿拉伯數字轉繁中格式範例
最後附上測試程式:
var basePath = AppDomain.CurrentDomain.BaseDirectory;
var baseFont = BaseFont.CreateFont($"{basePath}fonts/TW-Kai-98_1.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
var NORMAL = new Font(baseFont, 12, Font.NORMAL);
var document = new Document();
var writer = PdfWriter.GetInstance(document, new FileStream(string.Format("{0}helloworld.pdf", AppDomain.CurrentDomain.BaseDirectory), FileMode.OpenOrCreate));
writer.InitialLeading = 30;
document.Open();
document.Add(new Chunk("測試列表:", NORMAL));
document.Add(Chunk.NEWLINE);
var list1 = new iTextSharp.Extensions.ChineseList();
for (var i = 0; i < 10; i++)
{
list1.Add(new iTextSharp.text.ListItem((i + 1).ToString(), NORMAL));
}
document.Add(list1);
document.Add(Chunk.NEWLINE);
var list2 = new iTextSharp.Extensions.ChineseList(false);
for (var i = 0; i < 10; i++)
{
list2.Add(new iTextSharp.text.ListItem((i + 1).ToString(), NORMAL));
}
document.Add(list2);
document.Add(Chunk.NEWLINE);
document.Close();
結果:
經過看到這篇文章 不好意思另外問個問題
請問大大們有使用itextsharp轉PDF print特殊字元嗎??
例如 "®" 目前我是使用特殊字元的unicode value /u00ae來做轉換
參考這篇
https://stackoverflow.com/questions/31268867/itext-unable-to-print-mathematical-characters-like-%E2%88%88-%E2%88%A9-%E2%88%91-%E2%88%AB-%E2%88%86-%E2%88%9A-%E2%88%A0
但是如果從Database撈出一串文字 例如"ABCD®(EFGH®)"這樣該怎麼做呢??
大大應該是沒有掛字型或掛的字型沒有 ® 這個字。
我用微軟正黑體做了範例,給您參考看看。
var basePath = AppDomain.CurrentDomain.BaseDirectory;
//微軟正黑體字型
var baseFont = BaseFont.CreateFont($"{basePath}fonts/msjh.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
var NORMAL = new Font(baseFont, 12, Font.NORMAL);
var document = new Document();
var writer = PdfWriter.GetInstance(document, new FileStream(string.Format("{0}helloworld.pdf", AppDomain.CurrentDomain.BaseDirectory), FileMode.OpenOrCreate));
writer.InitialLeading = 30;
document.Open();
document.Add(new Chunk("ABCD®(EFGH®)", NORMAL));
document.Add(Chunk.NEWLINE);
document.Close();
結果
如果對難字有興趣,可以參考 [C#] 難字處理心得 這篇文章。
這是目前編輯器畫面
這是pdf畫面
確實是有抓到
目前我是猜是字型問題,目前程式是用
public ListItem(Chunk chunk);
那我在想辦法帶入font參數就可以了嗎? 謝謝