混合方向PDF將每頁列印為橫向

This article was translated from English: Does it need improvement?
Translated
View the article in English

IronPrint 2026.1.5 在列印同時包含直向和橫向頁面的PDF時,不保留每頁的方向。 每頁到達列印機時均為橫向,無論其原始方向如何。

這會影響2026.1.5在Windows 10和Windows Server 2022上的.NET 8版本。此版本沒有修正的版本。

引擎將整個文件設置為單一方向,而不是讀取每頁的尺寸。 將文件分割為相同方向頁面的組合並分別列印每個組合可恢復正確的輸出。

解決方案

建議:將PDF按方向一致的批次列印,而不是作為單一作業。

1. 檢測每頁的方向

打開PDF並比較每一頁的寬度與高度。 寬度大於高度的頁面為橫向; 其他為直向。

2. 將連續相同方向的頁面分組

按順序瀏覽頁面,並在方向轉變時開始新的批次。 每個批次最終作為一個連續的頁面範圍,具有一種方向。

3. 將每個批次作為獨立作業列印

分開發送每個範圍讓列印機應用該範圍的方向,而不是強迫整個文件轉為橫向。

4. 手動處理多份拷貝

由於文件現在分散在多個作業中,每次複製時都要迴圈一次並完整地印出批次序列。這可使每份拷貝的頁面順序保持完整。

完整實作如下:

using IronPrint;
using IronPdf;
await PrintDocumentByOrientationBatchesAsync(
    documentPath: documentPath,
    printerName: printerName,
    numberOfCopies: effectiveCopies);
async Task PrintDocumentByOrientationBatchesAsync(
    string documentPath,
    string printerName,
    int numberOfCopies)
{
    var tempFolder = Path.Combine(
        Path.GetTempPath(),
        "ironprint-orientation-workaround",
        Guid.NewGuid().ToString("N"));
    Directory.CreateDirectory(tempFolder);
    try
    {
        using var pdf = PdfDocument.FromFile(documentPath);
        var batches = GetConsecutiveOrientationBatches(pdf);
        // Since the document is printed in multiple jobs, copies are handled manually
        // to preserve the full document order per copy.
        for (var copy = 1; copy <= numberOfCopies; copy++)
        {
            foreach (var batch in batches)
            {
                var batchPath = Path.Combine(
                    tempFolder,
                    $"copy_{copy}_pages_{batch.StartPageNumber}_{batch.EndPageNumber}_{batch.Orientation}.pdf");
                using var batchPdf = pdf.CopyPages(batch.StartIndex, batch.EndIndex);
                batchPdf.SaveAs(batchPath);
                var printSettings = new PrintSettings
                {
                    PrinterName = printerName,
                    NumberOfCopies = 1,
                    PaperOrientation = batch.Orientation == DetectedPageOrientation.Landscape
                        ? PaperOrientation.Landscape
                        : PaperOrientation.Portrait,
                    PaperSize = PaperSize.PrinterDefault
                };
                await Printer.PrintAsync(batchPath, printSettings);
                // Optional delay to help ensure print jobs are queued in order.
                await Task.Delay(500);
            }
        }
    }
    finally
    {
        try
        {
            Directory.Delete(tempFolder, recursive: true);
        }
        catch
        {
            // Ignore cleanup errors in case the print spooler is still accessing the files.
        }
    }
}
List<PageOrientationBatch> GetConsecutiveOrientationBatches(PdfDocument pdf)
{
    var batches = new List<PageOrientationBatch>();
    if (pdf.PageCount == 0)
    {
        return batches;
    }
    var currentOrientation = GetPageOrientation(pdf.Pages[0].Width, pdf.Pages[0].Height);
    var batchStartIndex = 0;
    for (var pageIndex = 1; pageIndex < pdf.PageCount; pageIndex++)
    {
        var page = pdf.Pages[pageIndex];
        var pageOrientation = GetPageOrientation(page.Width, page.Height);
        if (pageOrientation != currentOrientation)
        {
            batches.Add(new PageOrientationBatch(
                StartIndex: batchStartIndex,
                EndIndex: pageIndex - 1,
                Orientation: currentOrientation));
            batchStartIndex = pageIndex;
            currentOrientation = pageOrientation;
        }
    }
    batches.Add(new PageOrientationBatch(
        StartIndex: batchStartIndex,
        EndIndex: pdf.PageCount - 1,
        Orientation: currentOrientation));
    return batches;
}
DetectedPageOrientation GetPageOrientation(double width, double height)
{
    return width > height
        ? DetectedPageOrientation.Landscape
        : DetectedPageOrientation.Portrait;
}
record PageOrientationBatch(
    int StartIndex,
    int EndIndex,
    DetectedPageOrientation Orientation)
{
    public int StartPageNumber => StartIndex + 1;
    public int EndPageNumber => EndIndex + 1;
}
enum DetectedPageOrientation
{
    Portrait,
    Landscape
}
using IronPrint;
using IronPdf;
await PrintDocumentByOrientationBatchesAsync(
    documentPath: documentPath,
    printerName: printerName,
    numberOfCopies: effectiveCopies);
async Task PrintDocumentByOrientationBatchesAsync(
    string documentPath,
    string printerName,
    int numberOfCopies)
{
    var tempFolder = Path.Combine(
        Path.GetTempPath(),
        "ironprint-orientation-workaround",
        Guid.NewGuid().ToString("N"));
    Directory.CreateDirectory(tempFolder);
    try
    {
        using var pdf = PdfDocument.FromFile(documentPath);
        var batches = GetConsecutiveOrientationBatches(pdf);
        // Since the document is printed in multiple jobs, copies are handled manually
        // to preserve the full document order per copy.
        for (var copy = 1; copy <= numberOfCopies; copy++)
        {
            foreach (var batch in batches)
            {
                var batchPath = Path.Combine(
                    tempFolder,
                    $"copy_{copy}_pages_{batch.StartPageNumber}_{batch.EndPageNumber}_{batch.Orientation}.pdf");
                using var batchPdf = pdf.CopyPages(batch.StartIndex, batch.EndIndex);
                batchPdf.SaveAs(batchPath);
                var printSettings = new PrintSettings
                {
                    PrinterName = printerName,
                    NumberOfCopies = 1,
                    PaperOrientation = batch.Orientation == DetectedPageOrientation.Landscape
                        ? PaperOrientation.Landscape
                        : PaperOrientation.Portrait,
                    PaperSize = PaperSize.PrinterDefault
                };
                await Printer.PrintAsync(batchPath, printSettings);
                // Optional delay to help ensure print jobs are queued in order.
                await Task.Delay(500);
            }
        }
    }
    finally
    {
        try
        {
            Directory.Delete(tempFolder, recursive: true);
        }
        catch
        {
            // Ignore cleanup errors in case the print spooler is still accessing the files.
        }
    }
}
List<PageOrientationBatch> GetConsecutiveOrientationBatches(PdfDocument pdf)
{
    var batches = new List<PageOrientationBatch>();
    if (pdf.PageCount == 0)
    {
        return batches;
    }
    var currentOrientation = GetPageOrientation(pdf.Pages[0].Width, pdf.Pages[0].Height);
    var batchStartIndex = 0;
    for (var pageIndex = 1; pageIndex < pdf.PageCount; pageIndex++)
    {
        var page = pdf.Pages[pageIndex];
        var pageOrientation = GetPageOrientation(page.Width, page.Height);
        if (pageOrientation != currentOrientation)
        {
            batches.Add(new PageOrientationBatch(
                StartIndex: batchStartIndex,
                EndIndex: pageIndex - 1,
                Orientation: currentOrientation));
            batchStartIndex = pageIndex;
            currentOrientation = pageOrientation;
        }
    }
    batches.Add(new PageOrientationBatch(
        StartIndex: batchStartIndex,
        EndIndex: pdf.PageCount - 1,
        Orientation: currentOrientation));
    return batches;
}
DetectedPageOrientation GetPageOrientation(double width, double height)
{
    return width > height
        ? DetectedPageOrientation.Landscape
        : DetectedPageOrientation.Portrait;
}
record PageOrientationBatch(
    int StartIndex,
    int EndIndex,
    DetectedPageOrientation Orientation)
{
    public int StartPageNumber => StartIndex + 1;
    public int EndPageNumber => EndIndex + 1;
}
enum DetectedPageOrientation
{
    Portrait,
    Landscape
}
Imports IronPrint
Imports IronPdf
Imports System.IO

Await PrintDocumentByOrientationBatchesAsync(documentPath:=documentPath, printerName:=printerName, numberOfCopies:=effectiveCopies)

Private Async Function PrintDocumentByOrientationBatchesAsync(documentPath As String, printerName As String, numberOfCopies As Integer) As Task
    Dim tempFolder = Path.Combine(Path.GetTempPath(), "ironprint-orientation-workaround", Guid.NewGuid().ToString("N"))
    Directory.CreateDirectory(tempFolder)
    Try
        Using pdf = PdfDocument.FromFile(documentPath)
            Dim batches = GetConsecutiveOrientationBatches(pdf)
            ' Since the document is printed in multiple jobs, copies are handled manually
            ' to preserve the full document order per copy.
            For copy = 1 To numberOfCopies
                For Each batch In batches
                    Dim batchPath = Path.Combine(tempFolder, $"copy_{copy}_pages_{batch.StartPageNumber}_{batch.EndPageNumber}_{batch.Orientation}.pdf")
                    Using batchPdf = pdf.CopyPages(batch.StartIndex, batch.EndIndex)
                        batchPdf.SaveAs(batchPath)
                        Dim printSettings = New PrintSettings With {
                            .PrinterName = printerName,
                            .NumberOfCopies = 1,
                            .PaperOrientation = If(batch.Orientation = DetectedPageOrientation.Landscape, PaperOrientation.Landscape, PaperOrientation.Portrait),
                            .PaperSize = PaperSize.PrinterDefault
                        }
                        Await Printer.PrintAsync(batchPath, printSettings)
                        ' Optional delay to help ensure print jobs are queued in order.
                        Await Task.Delay(500)
                    End Using
                Next
            Next
        End Using
    Finally
        Try
            Directory.Delete(tempFolder, recursive:=True)
        Catch
            ' Ignore cleanup errors in case the print spooler is still accessing the files.
        End Try
    End Try
End Function

Private Function GetConsecutiveOrientationBatches(pdf As PdfDocument) As List(Of PageOrientationBatch)
    Dim batches = New List(Of PageOrientationBatch)()
    If pdf.PageCount = 0 Then
        Return batches
    End If
    Dim currentOrientation = GetPageOrientation(pdf.Pages(0).Width, pdf.Pages(0).Height)
    Dim batchStartIndex = 0
    For pageIndex = 1 To pdf.PageCount - 1
        Dim page = pdf.Pages(pageIndex)
        Dim pageOrientation = GetPageOrientation(page.Width, page.Height)
        If pageOrientation <> currentOrientation Then
            batches.Add(New PageOrientationBatch(StartIndex:=batchStartIndex, EndIndex:=pageIndex - 1, Orientation:=currentOrientation))
            batchStartIndex = pageIndex
            currentOrientation = pageOrientation
        End If
    Next
    batches.Add(New PageOrientationBatch(StartIndex:=batchStartIndex, EndIndex:=pdf.PageCount - 1, Orientation:=currentOrientation))
    Return batches
End Function

Private Function GetPageOrientation(width As Double, height As Double) As DetectedPageOrientation
    Return If(width > height, DetectedPageOrientation.Landscape, DetectedPageOrientation.Portrait)
End Function

Private NotInheritable Class PageOrientationBatch
    Public Property StartIndex As Integer
    Public Property EndIndex As Integer
    Public Property Orientation As DetectedPageOrientation

    Public Sub New(StartIndex As Integer, EndIndex As Integer, Orientation As DetectedPageOrientation)
        Me.StartIndex = StartIndex
        Me.EndIndex = EndIndex
        Me.Orientation = Orientation
    End Sub

    Public ReadOnly Property StartPageNumber As Integer
        Get
            Return StartIndex + 1
        End Get
    End Property

    Public ReadOnly Property EndPageNumber As Integer
        Get
            Return EndIndex + 1
        End Get
    End Property
End Class

Private Enum DetectedPageOrientation
    Portrait
    Landscape
End Enum
$vbLabelText   $csharpLabel

GetConsecutiveOrientationBatches 為每個連續組合產生一個PaperOrientation。 作業之間的Task.Delay(500)有助於假脱机程式按順序排隊它們。

警告每個方向範圍都作為單獨的列印作業發送。 在物理列印機上,作業連續排隊,但在Microsoft Print to PDF或類似的虛擬列印機中,每個批次可能會提示輸出其自己的文件。

Curtis Chau
技術作家

Curtis Chau擁有Carleton大學的電腦科學學士學位,專精於前端開發,擁有Node.js、TypeScript、JavaScript和React的專業知識。Curtis熱衷於建立直觀且美觀的使用者介面,喜愛使用現代框架並建立結構良好、視覺吸引力的手冊。

除了開發,Curtis對物聯網(IoT)有濃厚的興趣,探索創新的方法來整合硬體和軟體。在空閒時間,他喜歡玩遊戲和建立Discord機器人,結合他對技術的熱愛與創造力。

準備好開始了嗎?
Nuget 下載 44,923 | 版本: 2026.7 剛剛發布
Still Scrolling Icon

仍在滾動?

想要快速證明嗎? PM > Install-Package IronPrint
運行範例 看看您的文件如何到達印表機。