Crea PDF con una scala di stampa di nessuno


2

Devo generare un documento pdf con le opzioni di stampa del ridimensionamento pagina impostate su "Nessuno" o "Dimensione effettiva"

Questa impostazione nel documento significherebbe che l'impostazione predefinita quando si apre il documento in Adobe Reader o in altri lettori PDF sarà "Non ridurre questa pagina per adattarla ai margini della stampante"

In Adobe Reader 10 l'impostazione che desidero controllare si trova nella finestra di dialogo Stampa e in "Dimensionamento e gestione delle pagine" l'opzione "Opzioni dimensioni" Vorrei che il documento fosse impostato su "Dimensioni effettive" anziché su "Riduci pagine di grandi dimensioni".

Ho parlato con le mie fonti e ho testato con la creazione / salvataggio di un documento PDF con Adobe Standard Edition e puoi impostare le proprietà Visualizza del documento su un valore predefinito per questa proprietà esatta e Adobe Reader rispetterà questo invece di utilizzare Adobe Reader predefinito che è shink.

Sto usando PDF Creator 1.5.0 per "stampare" il documento pfd che sembra consentire l'applicazione di postscript al documento. Tuttavia, potrei usare una stampante PDF alternativa se fosse adatta al mio scopo e avesse questa opzione. Non vedo alcuna opzione della GUI nelle impostazioni di PDF Creator per il controllo.

Sono abbastanza sicuro di poter usare ghostscript per applicare una proprietà ma devo sapere come farlo.

Aggiornamento : ho esaminato la specifica Adobe PDF e le proprietà del documento che sto cercando sembrano essere nella specifica PDF 1.6.

12.2 Preferenze del visualizzatore La voce ViewerPreferences nel catalogo di un documento (vedere 7.7.2, "Catalogo documenti") indica un dizionario delle preferenze del visualizzatore (PDF 1.2) che controlla il modo in cui il documento deve essere presentato sullo schermo o in stampa. Se non viene specificato tale dizionario, i lettori conformi devono comportarsi in base alle proprie impostazioni delle preferenze dell'utente. La Tabella 150 mostra i contenuti del dizionario delle preferenze del visualizzatore.

PrintScaling - (Opzionale; PDF 1.6) L'opzione di ridimensionamento della pagina che deve essere selezionata quando viene visualizzata una finestra di dialogo di stampa per questo documento. I valori validi sono Nessuno, che indica nessun ridimensionamento della pagina, e AppDefault, che indica il ridimensionamento di stampa predefinito del lettore conforme. Se questa voce ha un valore non riconosciuto, deve essere utilizzato AppDefault. Valore predefinito: AppDefault. Se la finestra di dialogo di stampa viene soppressa e i suoi parametri sono forniti da qualche altra fonte, questa voce deve comunque essere rispettata.

Questo è ESATTAMENTE ciò che voglio controllare tramite alcuni software di stampa PDF o ghostscript di terze parti. Non sono un esperto di PDF e non so come farlo.

Aggiornamento : ho sviluppato una soluzione utilizzando Pdf Creator e modificato la soluzione nella risposta accettata. Ho anche esaminato quanto segue che ha il potenziale per le applicazioni quando si utilizza un'API per generare il pdf.
Documenti solidi pdf

itextpdf - Disponibile anche in una versione C #


So molto di PDF e Ghostscript (almeno mi piace pensarlo) ... ma non capisco il tuo problema, scusa.
Kurt Pfeifle,

Scusate la prima volta che provo a commentare e il mio browser va fuori di testa, continuo a premere invio. e ora non riesco a modificare. Domanda semplice Voglio il parametro ghostscript opposto a -dPDFFitPage. Può essere fatto con Adobe Standard ... ma attraverso la GUI non conosco la proprietà da impostare.

Apri un PDF in Adobe Reader -> Stampa -> cerca sotto il titolo "Dimensionamento e gestione delle pagine" guarda "Opzioni dimensioni" e di solito il valore predefinito sarà "Scorri pagine di grandi dimensioni" (altri visualizzatori di PDF hanno un'impostazione simile ma per semplicità I mi attengo alle parole esatte di Adobe) voglio incorporare l'opzione di "Dimensione reale" nel documento. So che questo è possibile perché Adobe Standard (creatore completo) ti consente di impostarlo ed è onorato quando apri il PDF in Adobe Reader.

Come autore di una domanda, puoi sempre modificarla. Cerca di essere chiaro e logico. Inizia a dire quale software + versione stai attualmente usando e cosa vuoi ottenere. E dovresti farlo prima che venga ridimensionato o addirittura eliminato ... Attualmente inizi con "Ho bisogno di generare un PDF ..." senza dire quale software usi. Quindi continui a parlare di "Opzioni di stampa del ridimensionamento della pagina" ... che è qualcosa di completamente diverso da "generare un PDF" - la stampa di un PDF è una funzione di un visualizzatore di PDF, non di un generatore di PDF.
Kurt Pfeifle,

1
Nota anche che PDFFitPage non fa ciò che sembra pensare che faccia. Ridimensiona un file PDF in arrivo in modo che si adatti a dimensioni del supporto diverse. Non c'è nulla nel dispositivo pdfwrite di Ghostscript che altera il comportamento di stampa predefinito di un visualizzatore di PDF. In realtà non sono a conoscenza di alcun modo per farlo. Se hai un file PDF per il quale è possibile, ti suggerisco di renderlo pubblicamente disponibile, in modo che possiamo guardarlo.
KenS,

Risposte:


2

Ciò dovrebbe essere possibile specificando /PrintScaling /Nonenel ViewerPreferencesdict (vedere la sezione 12.2 in ISO 32000-1: 2008 .

Aggiornamento : prova questo:

[ {Catalog} << /ViewerPreferences << /PrintScaling /None >> >> /PUT
pdfmark

Vedi http://www.digipedia.pl/usenet/thread/1191/1835/

Aggiornamento : dal poster
La soluzione finale è stata quella di aggiungere la riga Postscript sopra riportata nel Postscript generato da PDF Creator utilizzando la funzione "Azioni" di PDF Creator. (Azione prima di salvare)

http://www.pdfforge.org/content/actions

Ho anche usato questo link come ispirazione per l'azione e ho guardato gli script vbs preinstallati per capire cosa bisognava fare per aggiungere informazioni al file PostScript convertito in pdf.

PDFCreator Document View settings - Sembra che uno script simile a questo sia stato incluso in PdfCreator.

Comunque questo è il mio script finale che può essere aggiunto a Pdf Creator per aggiungere la proprietà predefinita PrintScaling.

' SetPrintScalingNone.vbs script
' Author: Collin Kulbacki
' Version: 1.0.0.0
' Date: Oct 18, 2012
' Comment: This script Sets the ViewerPrefferences Print Scalling to none.

Option Explicit

Const AppTitle = "PDFCreator - SetPrintScallingNone"
Const ForReading = 1, ForAppending = 8

Dim objArgs, objNetwork, section, ini, fso, f
Dim fname, key, psFile, strTitle,  printScalingFile

Set objArgs = WScript.Arguments

If objArgs.Count = 0 Then
 MsgBox "This script needs a parameter!", vbExclamation, AppTitle
 WScript.Quit
End If

fname = objArgs(0)


Set ini = New IniFile
ini.Load fName, true

Set fso = CreateObject("Scripting.FileSystemObject")
printScalingFile = fso.GetParentFolderName(fName) & "\" & GenerateGUID & ".ps"
Set f = fso.OpenTextFile(printScalingFile, ForAppending, True)
f.writeline "[ {Catalog} << /ViewerPreferences << /PrintScaling /None >> >> /PUT pdfmark"

f.Close

Set objNetwork = CreateObject("WScript.Network")

set section = ini.AddSection(GenerateGUID)
section.AddKey("SessionId").Value = " "
section.AddKey("WinStation").Value = " "
section.AddKey("UserName").Value = objNetwork.UserName
section.AddKey("ClientComputer").Value = objNetwork.ComputerName
section.AddKey("SpoolFileName").Value = printScalingFile
section.AddKey("PrinterName").Value = " "
section.AddKey("JobId").Value = " "
section.AddKey("DocumentTitle").Value = "PrintScaling"

ini.Save fName, true



WScript.Quit



Private Function GenerateGUID()
 GenerateGUID = Replace(Mid(CreateObject("Scriptlet.TypeLib").GUID, 2, 36), "-", "")
End Function



' http://www.codeproject.com/Articles/21896/INI-Reader-Writer-Class-for-C-VB-NET-and-VBScript
' IniFile class used to read a nd write ini files by loading the file into memory
Class IniFile
    'List of IniSection objects keeps track of all the sections in the INI file
    Private m_pSections, OpenAsUnicode
    'Public constructor
    Public Sub Class_Initialize()
        Set m_pSections = CreateObject("Scripting.Dictionary")
        m_pSections.CompareMode = vbTextCompare
    End Sub

    'Returns an array of the IniSections in the IniFile
    Public Property Get Sections
         Sections = m_pSections.Items
    End Property

    'Load IniFile object with existing INI Data
    Public Sub Load( ByVal sFileName , ByVal bAppend )
        Dim intAsc1Chr, intAsc2Chr
        If Not bAppend Then RemoveAllSections() ' Clear the object...

        Dim objFSO : Set objFSO = CreateObject("Scripting.FileSystemObject") 
        Dim tempsection : Set tempsection = Nothing
        'Dim oReader : Set oReader = objFSO.OpenTextFile( sFileName, , , format )
        Dim oReader, Stream
        Set Stream = objFSO.OpenTextFile(sFileName, 1, False)
        intAsc1Chr = Asc(Stream.Read(1))
        intAsc2Chr = Asc(Stream.Read(1))
        Stream.Close

        ' (255, 254 == FF, FE -> UniCode) Or (91, 0 == [ '\0' -> Widechar inf file from pdfcmon.dll)
        If (intAsc1Chr = 255 And intAsc2Chr = 254) Or (intAsc1Chr = 91 And intAsc2Chr = 0) Then 
            OpenAsUnicode = True
        Else
            OpenAsUnicode = False
        End If

        Set oReader = objFSO.OpenTextFile( sFileName, 1, 0, OpenAsUnicode )
        Dim regexsection : set regexsection = new regexp 
        Dim regexkey : Set regexkey = new regexp
        Dim regexcomment : Set regexcomment = new regexp

        regexcomment.Pattern = "^([\s]*#.*)"
        regexcomment.Global = False
        regexcomment.IgnoreCase = True
        regexcomment.MultiLine = False

        ' Left for history
        'regexsection.Pattern = "\[[\s]*([^\[\s].*[^\s\]])[\s]*\]"
        'regexsection.Pattern = "^[\s]*\[[\s]*([^\[\s].*[^\s\]])[\s]*\][\s]*$"
        regexsection.Pattern = "^\s*\[\s*(.*[^\s])\s*\]\s*$"
        regexsection.Global = False
        regexsection.IgnoreCase = True
        regexsection.MultiLine = False

        regexkey.Pattern = "^\s*([^=\s]*)[^=]*=(.*)" 
        regexkey.Global = False
        regexkey.IgnoreCase = True
        regexkey.MultiLine = False

        While Not oReader.AtEndOfStream
            Dim line : line = oReader.ReadLine()
            If line <> "" Then
                Dim m
                If regexcomment.Test(line) Then
                    Set m = regexcomment.Execute(line)
                    'WScript.Echo("Skipping Comment " & m.Item(0).subMatches.Item(0) )
                ElseIf regexsection.Test(line) Then
                    Set m = regexsection.Execute(line)
                    'WScript.Echo("Adding section [" & m.Item(0).subMatches.Item(0) &"]" )
                    Set tempsection = AddSection( m.Item(0).subMatches.Item(0) )
                ElseIf regexkey.Test(line) And Not tempsection Is Nothing Then
                    Set m = regexkey.Execute(line)
                    'WScript.Echo("Adding Key ["& m.Item(0).subMatches.Item(0) &"]=["& m.Item(0).subMatches.Item(1) &"]" )
                    tempsection.AddKey( m.Item(0).subMatches.Item(0) ).Value = m.Item(0).subMatches.Item(1)
                ElseIf Not tempsection Is Nothing Then
                    'WScript.Echo("Adding Key ["& line &"]" )
                    tempsection.AddKey( line )
                'Else
                 '   WScript.Echo("Skipping unknown type of data: " & line)
                End If
            End If
        Wend
        oReader.Close()
    End Sub

    'Allows you to do a save the IniFile resident in memory to file
    Public Sub Save(ByVal sFileName, ByVal AsUnicode)
        Dim objFSO : Set objFSO = CreateObject("Scripting.FileSystemObject")
        Dim oWriter : Set oWriter = objFSO.CreateTextFile( sFileName , True, AsUnicode )

        Dim s 'IniSection
        Dim k 'IniKey
        For Each s In Sections
            'WScript.Echo("Writing Section: " & s.Name)
            oWriter.WriteLine("[" & s.Name & "]")
            For Each k In s.Keys
                If k.Value <> vbNullString Then
                    'WScript.Echo("Writing Key: "&k.Name&"="&k.Value)
                    oWriter.WriteLine(k.Name & "="& k.Value )
                Else
                    'WScript.Echo("Writing Key: "&k.Name)
                    oWriter.WriteLine(k.Name)
                End if
            Next
        Next
        oWriter.Close()
    End Sub

    'Returns the IniSection object associated with a section name
    Public Function GetSection(ByVal sSection )
        Set GetSection = Nothing
        sSection = Trim(sSection) 'Trim spaces
        If Len( sSection ) <> 0 Then
            If m_pSections.Exists( sSection ) Then
                Set GetSection = m_pSections.Item(sSection)
            End If
        End If
    End Function

    ' Adds a section to the IniFile object, returns a IniSection object
    Public Function AddSection(ByVal sSection )
        Set AddSection = Nothing
        If StrComp(TypeName(sSection),"IniSection",1) = 0 Then 
            If Not sSection Is Nothing Then
                ' Only purpose is to be used by child to re-insert
                If Not sSection Is Nothing Then
                    If Not m_pSections.Exists( sSection.Name ) Then
                        Set m_pSections.Item( sSection.Name ) = sSection
                        Set AddSection = sSection
                    End If
                End If
            End If 
        ElseIf StrComp(TypeName(sSection),"String",1) = 0 Then
            sSection = Trim(sSection)
            If Len( sSection ) <> 0 Then 
                If m_pSections.Exists( sSection ) Then
                    Set AddSection = m_pSections.Item(sSection)
                Else
                    Dim s : Set s = New IniSection
                    Call s.Init( Me , sSection )
                    Set m_pSections.Item(sSection) = s
                    Set AddSection = s
                End If
            End If      
        End If
    End Function

    ' Removes all existing sections (clears the object) 
    Public Sub RemoveAllSections()
        Call m_pSections.RemoveAll()
    End Sub

    ' Remove a section by name or section object
    Public Function RemoveSection(ByVal Obj)
        RemoveSection = False
        If StrComp(TypeName(Obj),"IniSection",1) = 0 Then 
            If Not Obj Is Nothing Then
                m_pSections.Remove(Obj.Name)
                RemoveSection = True
            End If 
        ElseIf StrComp(TypeName(Obj),"String",1) = 0 Then
            RemoveSection = RemoveSection( GetSection(Obj) )
        End If 
    End Function

    ' Remove a key by section namd and key name
    Public Function RemoveKey(ByVal sSection , ByVal sKey)
        RemoveKey = False
        Dim s : Set s = GetSection(sSection)
        If Not s Is Nothing Then
            RemoveKey = s.RemoveKey( sKey )
        End If
    End Function

    ' Returns a KeyValue in a certain section
    Public Function GetKeyValue(ByVal sSection , ByVal sKey )
        GetKeyValue = vbNullString
        Dim s : Set s = GetSection(sSection)
        If Not s Is Nothing Then
            Dim k : Set k = s.GetKey(sKey)
            If Not k Is Nothing Then
                GetKeyValue = k.Value
            End If
        End If
    End Function

    ' Sets a KeyValuePair in a certain section
    Public Function SetKeyValue(ByVal sSection , ByVal sKey , ByVal sValue )
        SetKeyValue = False
        Dim s : Set s = AddSection(sSection)
        If Not s Is Nothing Then
            Dim k : Set k = s.AddKey(sKey)
            If Not s Is Nothing Then
                k.Value = sValue
                SetKeyValue = True
            End If
        End If
    End Function

    ' Renames an existing section returns true on success, false if the section didn't exist or there was another section with the same sNewSection
    Public Function RenameSection(ByVal sSection , ByVal sNewSection)
        ' Note string trims are done in lower calls.
        RenameSection = False
        Dim s : Set s = GetSection(sSection)
        If Not s Is Nothing Then
            RenameSection = s.SetName(sNewSection)
        End If
    End Function

    ' Renames an existing key returns true on success, false if the key didn't exist or there was another section with the same sNewKey
    Public Function RenameKey(ByVal sSection , ByVal sKey, ByVal sNewKey)
        ' Note string trims are done in lower calls.
        RenameKey = False
        Dim s : Set s = GetSection(sSection)
        If Not s Is Nothing Then
            Dim k : Set k = s.GetKey(sKey)
            If Not k Is Nothing Then
                RenameKey = k.SetName(sNewKey)
            End If
        End If
    End Function

End Class


'IniSection Class 
Class IniSection
   ' IniFile IniFile object instance
   Private m_pIniFile
   ' Name of the section
   Private m_sSection
   ' List of IniKeys in the section
   Private m_keys

   'Friend constuctor so objects are internally managed
   Public Sub Class_Initialize
       Set m_pIniFile = Nothing
       m_sSection = ""
       Set m_keys = CreateObject("Scripting.Dictionary")
       m_keys.CompareMode = vbTextCompare
   End Sub

    ' Function only works once...
    Public Sub Init( ByVal oIniFile , ByVal sSection )
        If m_pIniFile is Nothing Then 
            Set m_pIniFile = oIniFile
            m_sSection = sSection
        End If  
    End Sub

    'Returns an array of the IniKeys in the IniFile
    Public Property Get Keys
         Keys = m_keys.Items
    End Property

   'Returns the section name
   Public Property Get Name
           name = m_sSection
   End Property

   'Set the section name
   'Returns true on success, False if key already exists in the section
   Public Function SetName(ByVal sSection)
       SetName = False  ' Default
       sSection = Trim(sSection)
       If Len( sSection ) <> 0 Then
           Dim s : Set s = m_pIniFile.GetSection(sSection)
           If Not s Is Me And Not s Is Nothing Then Exit Function
           Call m_pIniFile.RemoveSection(Me)
           m_sSection = sSection
           Call m_pIniFile.AddSection(Me)           
           SetName = True
       End If
   End Function

   'Returns the section name
   Public Function GetName()
           GetName = m_sSection
   End Function

   'Adds a key to the IniSection object
   'Returns Nothing on failure
    Public Function AddKey(ByVal sKey)
        Set AddKey = Nothing
        ' Is this a string or object of IniKey
        If StrComp(TypeName(sKey),"IniKey",1) = 0 Then 
            ' Only purpose is to be used by child to re-insert
            If Not sKey Is Nothing Then
                If Not m_keys.Exists( sKey.Name ) Then
                    Set m_keys.Item(sKey.Name) = sKey
                    Set AddKey = sKey
                End If
            End If
        ElseIf StrComp(TypeName(sKey),"String",1) = 0 Then
            ' String was passed...
            sKey = Trim(sKey)
            If Len(sKey) <> 0 Then
                If m_keys.Exists( sKey ) Then
                    Set AddKey = m_keys.Item(sKey)
                Else
                    Dim k : Set k = New IniKey
                    Call k.Init( Me , sKey )
                    Set m_keys.Item(sKey) = k
                    Set AddKey = k
                End If
            End If
        End If        
   End Function

   'Returns a IniKey
   'Returns Nothing on failure 
    Public Function GetKey(ByVal sKey)
        Set GetKey = Nothing
        sKey = Trim(sKey)
        If Len(sKey) <> 0 Then
            If m_keys.Exists( sKey ) Then
                Set GetKey = m_keys.Item(sKey)
            End If 
        End If
    End Function

   'Removes all the keys in the section
   Public Sub RemoveAllKeys()
       Call m_keys.RemoveAll()
   End Sub

   'Removes a single key by IniKey object by string or object
   Public Function RemoveKey(ByVal Obj)
        RemoveKey = False
        If StrComp(TypeName(Obj),"IniKey",1) = 0 Then 
            If Not Obj Is Nothing Then
                m_keys.Remove(Obj.Name)
                RemoveKey = True
            End If
        ElseIf StrComp(TypeName(Obj),"String",1) = 0 Then
            RemoveKey = RemoveKey( GetKey(Obj) )
        End If        
   End Function

End Class  ' End of IniSection

'IniKey Class
Class IniKey
    ' Name of the Key
    Private m_sKey
    ' Value associated
    Private m_sValue
    ' Pointer to the parent CIniSection
    Private m_pSection

    'Friend constuctor so objects are internally managed
    Public Sub Class_Initialize
        m_sKey = ""
        m_sValue = ""
        Set m_pSection = Nothing
    End Sub

    'Returns the key's parent IniSection
    Public Sub Init( ByVal oIniSection , ByVal sKey )
           If m_pSection Is Nothing Then
                Set m_pSection = oIniSection
                m_sKey = sKey
           End If 
    End Sub

    'Returns the name of the Key
    Public Property Get Name
            name = m_sKey
    End Property

'     'Gets\Sets the value associated with the Key
     Public Property Let Value( strKeyValue )
             m_sValue = strKeyValue
     End Property

    'Gets\Sets the value associated with the Key
    Public Property Get Value()
            value = m_sValue
    End Property

    'Sets the key name
    'Returns true on success, fails if the section name sKeyName already exists
    Public Function SetName(ByVal sKey )
        SetName = False
        sKey = Trim(sKey)
        If Len(sKey) <> 0 Then
            Dim s : Set s = m_pSection.GetKey(sKey)
            If Not s Is Me And Not s Is Nothing Then Exit Function
            Call m_pSection.RemoveKey(Me)
            ' Set our new name
            m_sKey = sKey
            ' Put our own object back
            Call m_pSection.AddKey(Me)
            SetName = True
        End If
    End Function

    ' Returns the current key name
    Public Function GetName()
            GetName = m_sKey
    End Function

End Class

Non posso prendermi il merito per la classe di file ini utilizzata per analizzare l'output di PdfCreator fornito tramite gli script vbs esistenti in PdfCreator.


1

Controllando la versione 9 del riferimento pdfmark, non riesco a vedere alcun pdfmark che influisce sulle preferenze del visualizzatore. Quindi non c'è modo per raggiungere questo obiettivo utilizzando Ghostscript senza modificare il dispositivo pdfwrite.

Il dispositivo pdfwrite di Ghostscript non emette affatto un dizionario ViewerPreferences nell'oggetto Catalog, quindi dovresti aggiungerne uno.


Grazie per l'informazione, forse ghostscript è la tecnologia sbagliata di cui chiedere. La mia conoscenza è estremamente minima. Da quanto ho capito, ho pensato che ghostscript utilizza ps2pdf e sembrava che ps2pdf potesse aggiungere / modificare il catalogo. Ma come ho detto, sono un novellino di pdf / ghostscript e non riesco a capire quale sia la sintassi. Anche dopo aver letto questo. ghostscript.com/doc/current/Ps2pdf.htm#Orientation
Collin

@Collin: credo che questo possa essere fatto funzionare; vedi l'aggiornamento alla mia risposta.
Martin Schröder,

ps2pdf (in almeno una incarnazione con quel nome) è solo uno script che chiama Ghostscript. Se è coinvolto Ghostscript, qualsiasi altra cosa lo utilizzerà, non viceversa. Ghostscript è la tecnologia di base.
KenS,

Martin, la tua risposta è esattamente il modo corretto di farlo con pdfmark, credo, con un piccolo problema. Come ho detto, Ghostscript non emette ViewerPreferences nel dizionario del catalogo e poiché crea il catalogo come richiesto (alla fine del processo) non è possibile aggiungere nulla al dizionario del catalogo nel corso del lavoro. L'unico modo per farlo con Ghostscript, per quanto posso vedere, è estrarre il tuo editor preferito e compilatore C e iniziare a scrivere codice. Il catalogo è scritto in gdevpdf.c, pdf_close () alla riga 2421.
KenS,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.