使用C#修改PDF頁(yè)面大小為標(biāo)準(zhǔn)尺寸或自定義尺寸
引言
最近處理 PDF 文件時(shí)遇到一個(gè)需求:把已有 PDF 的頁(yè)面尺寸統(tǒng)一調(diào)整一下。有些文件是系統(tǒng)導(dǎo)出的,有些是掃描件,頁(yè)面大小不一致,后面打印或歸檔時(shí)不太方便。
這里記錄一下用 C# 調(diào)整 PDF 頁(yè)面大小的做法。核心思路不是直接改原 PDF 的頁(yè)面屬性,而是重新創(chuàng)建一個(gè) PDF,把原來(lái)的每一頁(yè)作為模板繪制到新頁(yè)面上。
這樣處理后,原頁(yè)面里的文字、圖片、表格等內(nèi)容都能保留下來(lái),同時(shí)可以把頁(yè)面尺寸改成 A4、A3、A1 這類(lèi)標(biāo)準(zhǔn)尺寸,也可以改成自己指定的寬高。
安裝 Spire.PDF
示例里用到的是 Spire.PDF。如果是 NuGet 包管理器,可以直接安裝:
PM> Install-Package Spire.PDF
也可以用 .NET CLI:
dotnet add package Spire.PDF
代碼中需要引入下面幾個(gè)命名空間:
using Spire.Pdf; using Spire.Pdf.Graphics; using System.Drawing;
基本處理思路
調(diào)整頁(yè)面大小時(shí),可以按這個(gè)流程來(lái)做:
先讀取原 PDF,然后創(chuàng)建一個(gè)新的 PDF。接著遍歷原 PDF 的每一頁(yè),在新 PDF 里創(chuàng)建目標(biāo)尺寸的新頁(yè)面,再把原頁(yè)面生成模板并繪制到新頁(yè)面上。
聽(tīng)起來(lái)步驟比較多,但代碼其實(shí)不復(fù)雜。這里有一個(gè)比較重要的設(shè)置:
PdfTextLayout layout = new PdfTextLayout(); layout.Layout = PdfLayoutType.OnePage;
這個(gè)設(shè)置的作用是讓原頁(yè)面內(nèi)容適配到新頁(yè)面中。如果不加,在頁(yè)面尺寸變化比較明顯時(shí),內(nèi)容可能不會(huì)按照預(yù)期縮放。
一、把 PDF 頁(yè)面改成標(biāo)準(zhǔn)紙張大小
如果只是想改成 A4、A3、A1、Letter、Legal 這類(lèi)常見(jiàn)尺寸,可以直接使用 PdfPageSize。
下面的示例是把原 PDF 的頁(yè)面統(tǒng)一改成 A1。
using Spire.Pdf;
using Spire.Pdf.Graphics;
using System.Drawing;
namespace ResizePdfToStandardSize
{
class Program
{
static void Main(string[] args)
{
// 讀取原始 PDF
PdfDocument sourcePdf = new PdfDocument();
sourcePdf.LoadFromFile("Sample.pdf");
// 創(chuàng)建新的 PDF
PdfDocument outputPdf = new PdfDocument();
foreach (PdfPageBase sourcePage in sourcePdf.Pages)
{
// 新建 A1 頁(yè)面,頁(yè)邊距設(shè)置為 0
PdfPageBase newPage = outputPdf.Pages.Add(PdfPageSize.A1, new PdfMargins(0));
// 讓原頁(yè)面內(nèi)容適配到新頁(yè)面
PdfTextLayout layout = new PdfTextLayout();
layout.Layout = PdfLayoutType.OnePage;
// 把原頁(yè)面做成模板
PdfTemplate template = sourcePage.CreateTemplate();
// 繪制到新頁(yè)面
template.Draw(newPage, new PointF(0, 0), layout);
}
outputPdf.SaveToFile("ResizeToA1.pdf");
sourcePdf.Close();
outputPdf.Close();
}
}
}
如果要改成 A4,只需要把這一行:
PdfPageBase newPage = outputPdf.Pages.Add(PdfPageSize.A1, new PdfMargins(0));
改成:
PdfPageBase newPage = outputPdf.Pages.Add(PdfPageSize.A4, new PdfMargins(0));
常用的尺寸可以這樣寫(xiě):
PdfPageSize.A4 PdfPageSize.A3 PdfPageSize.Letter PdfPageSize.Legal
這里的 new PdfMargins(0) 表示不額外加頁(yè)邊距。如果想讓內(nèi)容四周留一點(diǎn)空白,也可以設(shè)置成:
new PdfMargins(20)
不過(guò)加了頁(yè)邊距以后,實(shí)際可繪制區(qū)域會(huì)變小,頁(yè)面內(nèi)容的縮放效果也會(huì)受到影響。
二、把 PDF 頁(yè)面改成自定義尺寸
如果目標(biāo)尺寸不是標(biāo)準(zhǔn)紙張,比如要做票據(jù)、標(biāo)簽、電子書(shū)頁(yè)面,或者要適配某個(gè)固定打印模板,就需要自定義寬高。
Spire.PDF 里頁(yè)面尺寸的單位是 point。
1 inch = 72 points。
如果你的尺寸是英寸、毫米或厘米,可以先轉(zhuǎn)換成 point,再創(chuàng)建頁(yè)面。
下面示例把頁(yè)面尺寸改成 6.5 × 8.5 英寸。
using Spire.Pdf;
using Spire.Pdf.Graphics;
using System.Drawing;
namespace ResizePdfToCustomSize
{
class Program
{
static void Main(string[] args)
{
PdfDocument sourcePdf = new PdfDocument();
sourcePdf.LoadFromFile("Sample.pdf");
PdfDocument outputPdf = new PdfDocument();
// 單位轉(zhuǎn)換
PdfUnitConvertor convertor = new PdfUnitConvertor();
float width = convertor.ConvertUnits(6.5f, PdfGraphicsUnit.Inch, PdfGraphicsUnit.Point);
float height = convertor.ConvertUnits(8.5f, PdfGraphicsUnit.Inch, PdfGraphicsUnit.Point);
SizeF pageSize = new SizeF(width, height);
foreach (PdfPageBase sourcePage in sourcePdf.Pages)
{
PdfPageBase newPage = outputPdf.Pages.Add(pageSize, new PdfMargins(0));
PdfTextLayout layout = new PdfTextLayout();
layout.Layout = PdfLayoutType.OnePage;
PdfTemplate template = sourcePage.CreateTemplate();
template.Draw(newPage, new PointF(0, 0), layout);
}
outputPdf.SaveToFile("ResizeToCustomSize.pdf");
sourcePdf.Close();
outputPdf.Close();
}
}
}
這個(gè)寫(xiě)法適合尺寸來(lái)自業(yè)務(wù)需求的場(chǎng)景。比如設(shè)計(jì)稿給的是英寸,或者打印規(guī)格里寫(xiě)的是固定寬高,都可以先轉(zhuǎn)換成 point 再處理。
三、如果尺寸單位是毫米
打印類(lèi)需求里,毫米會(huì)更常見(jiàn)。比如想設(shè)置成 210mm × 297mm,可以這樣寫(xiě):
PdfUnitConvertor convertor = new PdfUnitConvertor(); float width = convertor.ConvertUnits(210f, PdfGraphicsUnit.Millimeter, PdfGraphicsUnit.Point); float height = convertor.ConvertUnits(297f, PdfGraphicsUnit.Millimeter, PdfGraphicsUnit.Point); SizeF pageSize = new SizeF(width, height);
然后創(chuàng)建頁(yè)面時(shí)直接使用這個(gè) pageSize:
PdfPageBase newPage = outputPdf.Pages.Add(pageSize, new PdfMargins(0));
這種方式比手動(dòng)計(jì)算 point 更穩(wěn)一些,也不容易寫(xiě)錯(cuò)單位。
四、為什么要用模板重新繪制
一開(kāi)始我也以為改頁(yè)面大小應(yīng)該就是修改頁(yè)面屬性。但 PDF 里的內(nèi)容位置、頁(yè)面尺寸、坐標(biāo)系統(tǒng)是關(guān)聯(lián)在一起的。直接改頁(yè)面尺寸,不一定能讓原來(lái)的內(nèi)容自動(dòng)適配。
所以更穩(wěn)的做法是:
PdfTemplate template = sourcePage.CreateTemplate(); template.Draw(newPage, new PointF(0, 0), layout);
也就是把原頁(yè)面當(dāng)成一個(gè)整體模板,再畫(huà)到目標(biāo)尺寸的新頁(yè)面上。
配合:
layout.Layout = PdfLayoutType.OnePage;
可以讓內(nèi)容盡量縮放到新頁(yè)面范圍內(nèi)。
不過(guò)也要注意,如果原頁(yè)面和目標(biāo)頁(yè)面比例差距太大,最終效果可能會(huì)出現(xiàn)比較大的留白,或者內(nèi)容看起來(lái)被壓縮。比如把橫向頁(yè)面強(qiáng)行轉(zhuǎn)成豎向 A4,就需要人工檢查一下效果。
五、標(biāo)準(zhǔn)尺寸和自定義尺寸怎么選
如果只是為了打印、歸檔、統(tǒng)一頁(yè)面規(guī)格,優(yōu)先用標(biāo)準(zhǔn)尺寸就行:
outputPdf.Pages.Add(PdfPageSize.A4, new PdfMargins(0));
如果是業(yè)務(wù)里有明確尺寸要求,比如標(biāo)簽、票據(jù)、證書(shū)、書(shū)籍頁(yè)面,那就用自定義尺寸:
outputPdf.Pages.Add(pageSize, new PdfMargins(0));
實(shí)際項(xiàng)目里,我更建議把目標(biāo)尺寸做成配置項(xiàng)。這樣后面要從 A4 改成 A3,或者從英寸改成毫米,不需要改太多代碼。
六、封裝成一個(gè)簡(jiǎn)單方法
如果項(xiàng)目里會(huì)多次用到,可以把邏輯簡(jiǎn)單封裝一下。
轉(zhuǎn)成標(biāo)準(zhǔn)尺寸
static void ResizeToStandardSize(string inputPath, string outputPath, SizeF targetSize)
{
PdfDocument sourcePdf = new PdfDocument();
sourcePdf.LoadFromFile(inputPath);
PdfDocument outputPdf = new PdfDocument();
foreach (PdfPageBase sourcePage in sourcePdf.Pages)
{
PdfPageBase newPage = outputPdf.Pages.Add(targetSize, new PdfMargins(0));
PdfTextLayout layout = new PdfTextLayout();
layout.Layout = PdfLayoutType.OnePage;
PdfTemplate template = sourcePage.CreateTemplate();
template.Draw(newPage, new PointF(0, 0), layout);
}
outputPdf.SaveToFile(outputPath);
sourcePdf.Close();
outputPdf.Close();
}
調(diào)用時(shí)可以這樣寫(xiě):
ResizeToStandardSize("Sample.pdf", "Output.pdf", PdfPageSize.A4);
如果是自定義尺寸,也可以先轉(zhuǎn)換單位:
PdfUnitConvertor convertor = new PdfUnitConvertor();
float width = convertor.ConvertUnits(6.5f, PdfGraphicsUnit.Inch, PdfGraphicsUnit.Point);
float height = convertor.ConvertUnits(8.5f, PdfGraphicsUnit.Inch, PdfGraphicsUnit.Point);
SizeF customSize = new SizeF(width, height);
ResizeToStandardSize("Sample.pdf", "Output.pdf", customSize);
七、幾個(gè)容易忽略的點(diǎn)
1. 不建議直接覆蓋原文件
頁(yè)面尺寸調(diào)整后,最好輸出成一個(gè)新的 PDF。確認(rèn)效果沒(méi)問(wèn)題后,再?zèng)Q定是否替換原文件。
Sample.pdf ResizeToA4.pdf
這樣出問(wèn)題也能回退。
2. 頁(yè)邊距會(huì)影響內(nèi)容大小
示例中用了 0 頁(yè)邊距:
new PdfMargins(0)
如果設(shè)置了頁(yè)邊距,內(nèi)容區(qū)域會(huì)變小,縮放后的內(nèi)容也會(huì)跟著變小。這個(gè)在打印場(chǎng)景里尤其要注意。
3. 批量轉(zhuǎn)換時(shí)要注意文件命名
如果批量處理多個(gè) PDF,不要所有輸出都叫 Output.pdf??梢栽谖募锛由铣叽缁驎r(shí)間:
report_A4.pdf report_A3.pdf report_custom.pdf
4. 頁(yè)面比例不一致時(shí)要人工檢查
程序可以完成頁(yè)面縮放,但不一定能保證視覺(jué)效果一定完美。尤其是下面幾種情況:
- 橫向頁(yè)面轉(zhuǎn)豎向頁(yè)面;
- 大圖紙縮小成 A4;
- 掃描件頁(yè)面邊緣有大量空白;
- 原 PDF 每頁(yè)尺寸本身不一致。
這類(lèi)文件建議轉(zhuǎn)換后抽查幾頁(yè)。
八、完整代碼參考
最后放一個(gè)稍微整理過(guò)的完整版本,標(biāo)準(zhǔn)尺寸和自定義尺寸都可以用。
using Spire.Pdf;
using Spire.Pdf.Graphics;
using System.Drawing;
namespace ResizePdfPage
{
class Program
{
static void Main(string[] args)
{
// 示例一:轉(zhuǎn)為 A4
ResizePdf("Sample.pdf", "ResizeToA4.pdf", PdfPageSize.A4);
// 示例二:轉(zhuǎn)為自定義尺寸,單位為英寸
PdfUnitConvertor convertor = new PdfUnitConvertor();
float width = convertor.ConvertUnits(6.5f, PdfGraphicsUnit.Inch, PdfGraphicsUnit.Point);
float height = convertor.ConvertUnits(8.5f, PdfGraphicsUnit.Inch, PdfGraphicsUnit.Point);
SizeF customSize = new SizeF(width, height);
ResizePdf("Sample.pdf", "ResizeToCustomSize.pdf", customSize);
}
static void ResizePdf(string inputPath, string outputPath, SizeF pageSize)
{
PdfDocument sourcePdf = new PdfDocument();
sourcePdf.LoadFromFile(inputPath);
PdfDocument outputPdf = new PdfDocument();
foreach (PdfPageBase sourcePage in sourcePdf.Pages)
{
PdfPageBase newPage = outputPdf.Pages.Add(pageSize, new PdfMargins(0));
PdfTextLayout layout = new PdfTextLayout();
layout.Layout = PdfLayoutType.OnePage;
PdfTemplate template = sourcePage.CreateTemplate();
template.Draw(newPage, new PointF(0, 0), layout);
}
outputPdf.SaveToFile(outputPath);
sourcePdf.Close();
outputPdf.Close();
}
}
}
結(jié)尾
整體看下來(lái),調(diào)整 PDF 頁(yè)面尺寸主要就是兩件事:
第一,確定目標(biāo)頁(yè)面大小,是用 A4、A3 這類(lèi)標(biāo)準(zhǔn)尺寸,還是用自定義寬高。
第二,把原 PDF 頁(yè)面作為模板繪制到新頁(yè)面上,并設(shè)置單頁(yè)適配。
如果只是統(tǒng)一打印尺寸,用 PdfPageSize.A4 這類(lèi)標(biāo)準(zhǔn)尺寸就夠了。
如果是特殊業(yè)務(wù)頁(yè)面,可以先用 PdfUnitConvertor 把英寸或毫米轉(zhuǎn)換成 point,再創(chuàng)建對(duì)應(yīng)尺寸的頁(yè)面。
實(shí)際使用時(shí),建議重點(diǎn)檢查輸出頁(yè)面的比例、留白和內(nèi)容縮放效果,尤其是原 PDF 頁(yè)面尺寸不統(tǒng)一的情況。
以上就是使用C#修改PDF頁(yè)面大小為標(biāo)準(zhǔn)尺寸或自定義尺寸的詳細(xì)內(nèi)容,更多關(guān)于C#修改PDF頁(yè)面大小的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Unity實(shí)現(xiàn)單機(jī)游戲每日簽到系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了Unity實(shí)現(xiàn)單機(jī)游戲每日簽到系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-04-04
使用C#與SQL Server數(shù)據(jù)庫(kù)進(jìn)行交互的詳細(xì)流程
本文詳細(xì)介紹了如何使用Visual Studio創(chuàng)建Windows窗體應(yīng)用程序連接本地SQL Server數(shù)據(jù)庫(kù),并實(shí)現(xiàn)數(shù)據(jù)插入、查詢(xún)和刪除等功能,通過(guò)步驟說(shuō)明和代碼示例,展示了如何使用DataGridView控件和按鈕控件與數(shù)據(jù)庫(kù)進(jìn)行交互,文章還總結(jié)了易錯(cuò)點(diǎn),需要的朋友可以參考下2025-11-11
在C#中靈活調(diào)整Excel表格列的位置的方法步驟
在數(shù)據(jù)處理與報(bào)表生成的日常開(kāi)發(fā)中,我們經(jīng)常需要調(diào)整Excel工作表的列順序,以匹配下游系統(tǒng)的字段要求、優(yōu)化數(shù)據(jù)展示結(jié)構(gòu)或統(tǒng)一多份報(bào)表的列布局,本文將介紹如何使用 .NET 平臺(tái)下的免費(fèi)Excel處理庫(kù),通過(guò)C#代碼實(shí)現(xiàn)Excel列位置的調(diào)整與重排,需要的朋友可以參考下2026-07-07
C#逐行分元素讀取記事本數(shù)據(jù)并寫(xiě)入數(shù)據(jù)庫(kù)的方法
這篇文章主要介紹了C#逐行分元素讀取記事本數(shù)據(jù)并寫(xiě)入數(shù)據(jù)庫(kù)的方法,通過(guò)StreamReader類(lèi)里的ReadLine()方法實(shí)現(xiàn)逐行讀取的功能,是非常實(shí)用的技巧,需要的朋友可以參考下2014-12-12
c#使用Unity粒子實(shí)現(xiàn)炮塔發(fā)射系統(tǒng)
Unity自帶粒子發(fā)射器、動(dòng)畫(huà)器、渲染器各兩種,利用Unity的粒子系統(tǒng)制作一個(gè)炮塔發(fā)射系統(tǒng),了解粒子系統(tǒng),必須先了解每一個(gè)屬性都代表了什么,之后才能根據(jù)這些原理來(lái)調(diào)整出自己滿(mǎn)意的效果2022-04-04

