Jump to content

Script to export worksheets properly to pdf.


Recommended Posts

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 by hippothamus
Link to comment

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...