Hippocode Posted December 19, 2013 Share Posted December 19, 2013 (edited) We all know we can't export worksheet properly to PDF due to the page print setting that doesn't work. I've always wanted to export X sheets on a chosen paper size, mostly A4. Instead of creating an Sheet Layer for each worksheet, with a manual made viewport that scales it down until it fits you can use this script to do that for you. It only needs one Sheetlayer for all of your worksheets btw. This script works pretty easy - choose a layername where an image of the ws will be stored. - Setup and choose a sheetlayer with the page size, sheet border and title block you want. Make sure the page is not moved. Loop this script for each worksheet you need within the export pdf script and there you go. Never need to make a viewport again to scale any worksheet ! This is pretty basic and might not work for each type and position of titleblock, it can also only scale down but it can be tweaked into anything. It reads the sheet border frame dimensions and margins and will place and scale the viewport where it belongs. There is an option to shift the viewport to the bottom / top. Batchprint all the way ! PROCEDURE CreateWsViewport(LayerName,DesignLayerName,SheetName :STRING; VAR FrameHd :HANDLE); VAR PrintLayerHd,ViewportHd,SheetHd,SheetImageHd, LayerHd :HANDLE; result,MoveToTop,MoveToBottom,IsTitleBlock_B,IsTitleBlock_T :BOOLEAN; Left,Top,Right,Bottom,StartScale,DBorder_h,DBorder_v,TitleBlock_h,Titleblock_v,Margin_L,Margin_R,Margin_T,Margin_B,MaxHeight,MaxWidth :REAL; TitleblockPos,SheetBorderName, ViewportName, DBCrit, Method :STRING; BEGIN { settings } MoveToTop:= FALSE; MoveToBottom:= TRUE; StartScale:= 10; ViewportName:= 'WsViewport'; { Delete the previous viewport incase this script is looped ? } IF GetObject(ViewportName) <> NIL THEN DelObject(GetObject(ViewportName)); { Select the print sheet layer } PrintLayerHd:=GetObject(DesignLayerName); { search the sheet border frame } Layer(DesignLayerName); FrameHd:=FActLayer; SheetBorderName:=GetName(GetParametricRecord(FrameHd)); WHILE ((SheetBorderName <> 'Drawing Border - Universal') AND (FrameHd <> NIL)) DO BEGIN FrameHd:=NextObj(FrameHd); SheetBorderName:=GetName(GetParametricRecord(FrameHd)); END; IF FrameHd=NIL THEN AlrtDialog('sheet border not found'); { load framedata } Result:=ValidNumStr(GetRField(FrameHd,SheetBorderName,'horizDimension'),DBorder_h); Result:=ValidNumStr(GetRField(FrameHd,SheetBorderName,'vertDimension'),DBorder_v); Result:=ValidNumStr(GetRField(FrameHd,SheetBorderName,'titleBlockH'),TitleBlock_h); Result:=ValidNumStr(GetRField(FrameHd,SheetBorderName,'titleBlockV'),Titleblock_v); Result:=ValidNumStr(GetRField(FrameHd,SheetBorderName,'leftMargin'),Margin_L); Result:=ValidNumStr(GetRField(FrameHd,SheetBorderName,'rightMargin'),Margin_R); Result:=ValidNumStr(GetRField(FrameHd,SheetBorderName,'topMargin'),Margin_T); Result:=ValidNumStr(GetRField(FrameHd,SheetBorderName,'bottomMargin'),Margin_B); Method:=GetRField(FrameHd,SheetBorderName,'Method'); TitleblockPos:=GetRField(FrameHd,SheetBorderName,'titleBlkPosition'); IF Pos('Bottom',TitleBlockPos) > 0 THEN IsTitleBlock_B:=TRUE; IF Pos('Top',TitleBlockPos) > 0 THEN IsTitleBlock_T:=TRUE; { define max dim of viewport to fit in frame} IF Method<>'Inside Dimensions' THEN BEGIN MaxHeight:=DBorder_v-Titleblock_v-Margin_T-Margin_B; MaxWidth:=DBorder_h-Margin_L-Margin_R; END ELSE BEGIN MaxHeight:=DBorder_v-Titleblock_v; MaxWidth:=DBorder_h; END; { create viewport on the print layer } ViewportHd:= CreateVP(PrintLayerHd); SetName(ViewportHd,ViewportName); { Select the worksheet } SheetHd:=GetObject(SheetName); { add worksheet image to layer } Layer(LayerName); { Delete all the previous wsImages on the worksheet layer } ForEachObjectInLayer(DeleteObject,0,0,0); { new worksheet image} SheetImageHd:=CreateWSImage(SheetHd,0,0); LayerHd:=GetLayer(SheetImageHd); Result:=SetVPLayerVisibility(ViewportHd,LayerHd,0); {Viewport Class Visibilities} Result:= SetVPClassVisibility (ViewportHd, GetClass(SheetImageHd), 0); {Viewport Data} { scale } SetObjectVariableReal (ViewportHd,1003,StartScale); { Projection type } SetObjectVariableInt (ViewportHd,1000,6); { Render Type } SetObjectVariableInt (ViewportHd,1001,0); {Perspective Distance} SetObjectVariableReal (ViewportHd,1002,6.024691); { project 2D } SetObjectVariableBoolean (ViewportHd,1005,TRUE); { Render Background } SetObjectVariableLongInt (ViewportHd,1006,0); { } Result := SetViewMatrix (ViewportHd,0,0,0,0,-0,0); ResetObject (ViewportHd); { Move the sheet center to the originpoint 0,0 } GetBBox (SheetImageHd, left, top, right, bottom); HMove (SheetImageHd,-(right-left)/2,(top-bottom)/2); { Reset the scale in case the image doesn't fit the current sheet frame} GetBBox (ViewportHd, left, top, right, bottom); While (Abs(Right-left) > MaxWidth) OR (Abs(top-bottom) > MaxHeight) DO BEGIN StartScale:=StartScale+1; SetObjectVariableReal (ViewportHd,1003,StartScale); ResetObject (ViewportHd); GetBBox (ViewportHd, left, top, right, bottom); END; {viewport is now in the middle of our print page, do we want to move it somewhere ? } If MoveToTop THEN BEGIN IF Method<>'Inside Dimensions' THEN HMove(ViewportHd,0,(DBorder_v/2-Margin_T) - Abs(bottom)) ELSE HMove(ViewportHd,0,(DBorder_v/2) - Abs(bottom)); IF IsTitleBlock_T THEN HMove(ViewportHd,0,-Titleblock_v); END ELSE IF MoveToBottom THEN BEGIN IF Method<>'Inside Dimensions' THEN HMove(ViewportHd,0,(-DBorder_v/2+Margin_B) + Abs(bottom)) ELSE HMove(ViewportHd,0,(-DBorder_v/2) + Abs(bottom)); IF IsTitleBlock_B THEN HMove(ViewportHd,0,+Titleblock_v); END; END; Working example how I implemented it making one pdf of A4 pages containing 3 types of unlimited worksheets: PROCEDURE PreparePrinting; VAR i,i_Page :INTEGER; WHd,WImageHd,WpHd,Frame :HANDLE; S_Error :STRING; Status,inSeparateDocuments :BOOLEAN; Pageresult :INTEGER; FUNCTION DeleteObject(h:Handle):BOOLEAN; BEGIN DelObject(h); END; PROCEDURE EachPage(DesignLayerName :STRING); PROCEDURE CreateWsViewport(LayerName,DesignLayerName,SheetName :STRING; VAR FrameHd :HANDLE); VAR PrintLayerHd,ViewportHd,SheetHd,SheetImageHd, LayerHd :HANDLE; result,MoveToTop,MoveToBottom,IsTitleBlock_B,IsTitleBlock_T :BOOLEAN; Left,Top,Right,Bottom,StartScale,DBorder_h,DBorder_v,TitleBlock_h,Titleblock_v,Margin_L,Margin_R,Margin_T,Margin_B,MaxHeight,MaxWidth :REAL; TitleblockPos,SheetBorderName, ViewportName, DBCrit, Method :STRING; BEGIN { settings } MoveToTop:= FALSE; MoveToBottom:= TRUE; StartScale:= 10; ViewportName:= 'WsViewport'; { Delete the previous viewport incase this script is looped ? } IF GetObject(ViewportName) <> NIL THEN DelObject(GetObject(ViewportName)); { Select the print sheet layer } PrintLayerHd:=GetObject(DesignLayerName); { search the sheet border frame } Layer(DesignLayerName); FrameHd:=FActLayer; SheetBorderName:=GetName(GetParametricRecord(FrameHd)); WHILE ((SheetBorderName <> 'Drawing Border - Universal') AND (FrameHd <> NIL)) DO BEGIN FrameHd:=NextObj(FrameHd); SheetBorderName:=GetName(GetParametricRecord(FrameHd)); END; IF FrameHd=NIL THEN AlrtDialog('sheet border not found'); { load framedata } Result:=ValidNumStr(GetRField(FrameHd,SheetBorderName,'horizDimension'),DBorder_h); Result:=ValidNumStr(GetRField(FrameHd,SheetBorderName,'vertDimension'),DBorder_v); Result:=ValidNumStr(GetRField(FrameHd,SheetBorderName,'titleBlockH'),TitleBlock_h); Result:=ValidNumStr(GetRField(FrameHd,SheetBorderName,'titleBlockV'),Titleblock_v); Result:=ValidNumStr(GetRField(FrameHd,SheetBorderName,'leftMargin'),Margin_L); Result:=ValidNumStr(GetRField(FrameHd,SheetBorderName,'rightMargin'),Margin_R); Result:=ValidNumStr(GetRField(FrameHd,SheetBorderName,'topMargin'),Margin_T); Result:=ValidNumStr(GetRField(FrameHd,SheetBorderName,'bottomMargin'),Margin_B); Method:=GetRField(FrameHd,SheetBorderName,'Method'); TitleblockPos:=GetRField(FrameHd,SheetBorderName,'titleBlkPosition'); IF Pos('Bottom',TitleBlockPos) > 0 THEN IsTitleBlock_B:=TRUE; IF Pos('Top',TitleBlockPos) > 0 THEN IsTitleBlock_T:=TRUE; { define max dim of viewport to fit in frame} IF Method<>'Inside Dimensions' THEN BEGIN MaxHeight:=DBorder_v-Titleblock_v-Margin_T-Margin_B; MaxWidth:=DBorder_h-Margin_L-Margin_R; END ELSE BEGIN MaxHeight:=DBorder_v-Titleblock_v; MaxWidth:=DBorder_h; END; { create viewport on the print layer } ViewportHd:= CreateVP(PrintLayerHd); SetName(ViewportHd,ViewportName); { Select the worksheet } SheetHd:=GetObject(SheetName); { add worksheet image to layer } Layer(LayerName); { Delete all the previous wsImages on the worksheet layer } ForEachObjectInLayer(DeleteObject,0,0,0); { new worksheet image} SheetImageHd:=CreateWSImage(SheetHd,0,0); LayerHd:=GetLayer(SheetImageHd); Result:=SetVPLayerVisibility(ViewportHd,LayerHd,0); {Viewport Class Visibilities} Result:= SetVPClassVisibility (ViewportHd, GetClass(SheetImageHd), 0); {Viewport Data} { scale } SetObjectVariableReal (ViewportHd,1003,StartScale); { Projection type } SetObjectVariableInt (ViewportHd,1000,6); { Render Type } SetObjectVariableInt (ViewportHd,1001,0); {Perspective Distance} SetObjectVariableReal (ViewportHd,1002,6.024691); { project 2D } SetObjectVariableBoolean (ViewportHd,1005,TRUE); { Render Background } SetObjectVariableLongInt (ViewportHd,1006,0); { } Result := SetViewMatrix (ViewportHd,0,0,0,0,-0,0); ResetObject (ViewportHd); { Move the sheet center to the originpoint 0,0 } GetBBox (SheetImageHd, left, top, right, bottom); HMove (SheetImageHd,-(right-left)/2,(top-bottom)/2); { Reset the scale in case the image doesn't fit the current sheet frame} GetBBox (ViewportHd, left, top, right, bottom); While (Abs(Right-left) > MaxWidth) OR (Abs(top-bottom) > MaxHeight) DO BEGIN StartScale:=StartScale+1; SetObjectVariableReal (ViewportHd,1003,StartScale); ResetObject (ViewportHd); GetBBox (ViewportHd, left, top, right, bottom); END; {viewport is now in the middle of our print page, do we want to move it somewhere ? } If MoveToTop THEN BEGIN IF Method<>'Inside Dimensions' THEN HMove(ViewportHd,0,(DBorder_v/2-Margin_T) - Abs(bottom)) ELSE HMove(ViewportHd,0,(DBorder_v/2) - Abs(bottom)); IF IsTitleBlock_T THEN HMove(ViewportHd,0,-Titleblock_v); END ELSE IF MoveToBottom THEN BEGIN IF Method<>'Inside Dimensions' THEN HMove(ViewportHd,0,(-DBorder_v/2+Margin_B) + Abs(bottom)) ELSE HMove(ViewportHd,0,(-DBorder_v/2) + Abs(bottom)); IF IsTitleBlock_B THEN HMove(ViewportHd,0,+Titleblock_v); END; END; BEGIN { voorbladen afdrukken } i:=1; WHILE GetObject(concat('wvb: voorblad ',i)) <> NIL DO BEGIN Whd:=GetObject(concat('wvb: voorblad ',i)); RecalculateWS(Whd); { create viewport } CreateWsViewport('wvb: werkbladen',DesignLayerName,concat('wvb: voorblad ',i),Frame); IF GetLayerByName(DesignLayerName) <> NIL THEN BEGIN Layer(DesignLayerName); pageResult := ExportPDFPages(DesignLayerName); END; i:=i+1; END; { totaalbladen afdrukken } i:=1; WHILE GetObject(concat('wvb: totaal ',i)) <> NIL DO BEGIN Whd:=GetObject(concat('wvb: totaalblad ',i)); RecalculateWS(Whd); { create viewport } CreateWsViewport('wvb: werkbladen',DesignLayerName,concat('wvb: totaal ',i),Frame); IF GetLayerByName(DesignLayerName) <> NIL THEN BEGIN Layer(DesignLayerName); pageResult := ExportPDFPages(DesignLayerName); END; i:=i+1; END; FOR i:=1 TO 30 DO BEGIN Whd:=GetObject(concat('wvb: blad ',i)); IF Whd <> NIL THEN BEGIN RecalculateWS(Whd); { create viewport } CreateWsViewport('wvb: werkbladen',DesignLayerName,concat('wvb: blad ',i),Frame); IF GetLayerByName(DesignLayerName) <> NIL THEN BEGIN Layer(DesignLayerName); pageResult := ExportPDFPages(DesignLayerName); END; END; END; END; BEGIN SetPref(407, TRUE); { compiler mode, remember to turn it off!!!! } inSeparateDocuments:=FALSE; IF AcquireExportPDFSettingsAndLocation(inSeparateDocuments) THEN BEGIN IF OpenPDFDocument(concat('A4_WVB')) THEN BEGIN EachPage('A4_WVB'); ClosePDFDocument; END; END; END; RUN(PreparePrinting); Edited December 19, 2013 by hippothamus Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.