4D Write to Write Pro Image in Header

Hello All,

Version 16.0, Mac

I am trying to access the PICT image in the header of more than 11K 4D Write documents to change it to a PNG or JPEG. There does not seem to be a way to programmatically get any details about this image because it is in the header. That is in either 4D Write or Write Pro.

Each of the 4D Write documents has had the references frozen to create a final document. The template has been updated to use a supported graphics format, but the legacy records have the old PICT reference. I was hoping to remove and replace the PICT with the new, supported graphic. The documents are stored in the data file.

Is there any way to do this, especially since the graphic is in the header? This is frustrating. Any suggestions would be appreciated.

Is it not possible to use WP Get header to get a header range and WP Get elements to get a collection of images within that range?

Thank you Keisuke,

This is not v18, I am stuck in version 16. Those commands are not in the older version. I am trying to move this project out of 32 bit to 64 and the DB is still being used, so doing that kind of jump is probably not wise without testing.

Perhaps you could use v18 to publish a “converter” API that the v16 app can somehow consume?

Try WR SET FRAME before you try to select the PICT

Hi William,

I have an old code to delete pictures from old 4D Write documents:
You can pick the needed parts for your conversion method.

  1. looping through all the WR records:
	FIRST RECORD([AdrTexte])
	DelBildCount:=0
	ON ERR CALL("BlobErr")
	WR ON ERROR ("BlobErr")
	$anzobj:=Records in selection([AdrTexte])
	$ok:=ioThermometer ((-1*$anzobj);"Entferne Bilder...";"Entferne Bilder...";True)
	$loop:=0
	<>TempArea:=_o_Open external window(0;0;-1;-1;0;"Textvorlagen";"_4D Write")
	While (Not(End selection([AdrTexte])))
		VChanged:=False
		WR_RemovePictures (->[AdrTexte]WRTextAlt;->[AdrTexte]WRBlob)
		  //do something
		If (VChanged)
			SAVE RECORD([AdrTexte])
		End if 
		NEXT RECORD([AdrTexte])
		$loop:=$loop+1
		$ok:=ioThermometer ($loop;String([AdrTexte]DatNew)+" ")
	End while 
	CLOSE WINDOW(<>TempArea)
	$ok:=ioThermometer ($anzobj+1000)
	UNLOAD RECORD([AdrTexte])

Method: WR_RemovePictures

  //wr Konvert Blob
C_POINTER($1;$2)
C_LONGINT($anzZeichen;$AnzAbs;$i;$anzpict)
C_LONGINT($AnzObj;$AnzHot;$AnzSeit;$Mod;$i;$Table;$Field;$Type)
C_LONGINT(<>TempArea;$Write)
C_TEXT($Name)
C_BOOLEAN($change)


If (Picture size($1->)>5) | (BLOB size($2->)>1)
	Write_BlobToArea (<>TempArea;$2;$1)
	WR SET AREA PROPERTY (0;wr save preview;0)
	WR SET AREA PROPERTY (0;wr confirm dialog;0)
	WR SET AREA PROPERTY (0;wr convert dialog;0)
	WR SET AREA PROPERTY (0;wr allow undo;0)
	WR SET FRAME (<>TempArea;wr text frame)
	$anzpict:=WR Count (<>TempArea;wr nb pictures in page)
	If ($anzpict>0)
		DelBildCount:=DelBildCount+$anzpict
		For ($i;$anzpict;1;-1)
			WR DELETE PICTURE IN PAGE (<>TempArea;$i)
		End for 
		VChanged:=True
	End if 
	$anzpict:=WR Count (<>TempArea;wr nb pictures in text flow)
	If ($anzpict>0)
		DelBildCount:=DelBildCount+$anzpict
		For ($i;$anzpict;1;-1)
			WR SELECT (<>TempArea;4;1)
			WR DELETE SELECTION (<>TempArea)
			  //  WR DELETE PICTURE IN PAGE (◊TempArea;$i)
		End for 
		VChanged:=True
	End if 
	WR SET FRAME (<>TempArea;wr right footer)
	
	$anzpict:=WR Count (<>TempArea;wr nb pictures in page)
	If ($anzpict>0)
		DelBildCount:=DelBildCount+$anzpict
		For ($i;$anzpict;1;-1)
			WR DELETE PICTURE IN PAGE (<>TempArea;$i)
		End for 
		VChanged:=True
	End if 
	$anzpict:=WR Count (<>TempArea;wr nb pictures in text flow)
	If ($anzpict>0)
		DelBildCount:=DelBildCount+$anzpict
		For ($i;$anzpict;1;-1)
			WR SELECT (<>TempArea;4;1)
			WR DELETE SELECTION (<>TempArea)
			  //  WR DELETE PICTURE IN PAGE (◊TempArea;$i)
		End for 
		
		VChanged:=True
	End if 
	WR SET FRAME (<>TempArea;wr text frame)
	
	WR SET FRAME (<>TempArea;wr right header)
	
	$anzpict:=WR Count (<>TempArea;wr nb pictures in page)
	If ($anzpict>0)
		DelBildCount:=DelBildCount+$anzpict
		For ($i;$anzpict;1;-1)
			WR DELETE PICTURE IN PAGE (<>TempArea;$i)
		End for 
		VChanged:=True
	End if 
	$anzpict:=WR Count (<>TempArea;wr nb pictures in text flow)
	If ($anzpict>0)
		DelBildCount:=DelBildCount+$anzpict
		For ($i;$anzpict;1;-1)
			WR SELECT (<>TempArea;4;1)
			WR DELETE SELECTION (<>TempArea)
			  //  WR DELETE PICTURE IN PAGE (◊TempArea;$i)
		End for 
		
		VChanged:=True
	End if 
	
	C_REAL(vwr_diffonfirst)
	vwr_diffonfirst:=WR Get doc property (<>TempArea;wr different on first page)
	If (vwr_diffonfirst=1)
		WR SET FRAME (<>TempArea;wr first footer)
		
		$anzpict:=WR Count (<>TempArea;wr nb pictures in page)
		If ($anzpict>0)
			DelBildCount:=DelBildCount+$anzpict
			For ($i;$anzpict;1;-1)
				WR DELETE PICTURE IN PAGE (<>TempArea;$i)
			End for 
			VChanged:=True
		End if 
		$anzpict:=WR Count (<>TempArea;wr nb pictures in text flow)
		If ($anzpict>0)
			DelBildCount:=DelBildCount+$anzpict
			For ($i;$anzpict;1;-1)
				WR SELECT (<>TempArea;4;1)
				WR DELETE SELECTION (<>TempArea)
				  //  WR DELETE PICTURE IN PAGE (◊TempArea;$i)
			End for 
			
			VChanged:=True
		End if 
		WR SET FRAME (<>TempArea;wr first header)
		
		$anzpict:=WR Count (<>TempArea;wr nb pictures in page)
		If ($anzpict>0)
			DelBildCount:=DelBildCount+$anzpict
			For ($i;$anzpict;1;-1)
				WR DELETE PICTURE IN PAGE (<>TempArea;$i)
			End for 
			VChanged:=True
		End if 
		$anzpict:=WR Count (<>TempArea;wr nb pictures in text flow)
		If ($anzpict>0)
			DelBildCount:=DelBildCount+$anzpict
			For ($i;$anzpict;1;-1)
				WR SELECT (<>TempArea;4;1)
				WR DELETE SELECTION (<>TempArea)
				  //  WR DELETE PICTURE IN PAGE (◊TempArea;$i)
			End for 
			
			VChanged:=True
		End if 
		
	End if 
	WR SET FRAME (<>TempArea;wr text frame)
	If (vChanged)
		Write_AreaToBlob (<>TempArea;$2;$1)
	End if 
	
End if 

Method Write_BlobToArea (loads WR doc from picture or blob to area:

C_LONGINT($1;$writeArea;$area;$vlCompressed)
C_POINTER($2;$blobArea;$3;$pictArea)
C_BLOB($vb_Blob)
C_PICTURE($pict)
SET BLOB SIZE($vb_Blob;0)
$writeArea:=$1
$blobArea:=$2
$pictArea:=$3
If (BLOB size($blobArea->)>3)
	$vb_Blob:=$blobArea->
	BLOB PROPERTIES($vb_Blob;$vlCompressed)
	If ($vlCompressed#Is not compressed)
		EXPAND BLOB($vb_Blob)
	End if 
	WR BLOB TO AREA ($writeArea;$vb_Blob)
Else 
	If (Picture size($pictArea->)>10)
		WR PICTURE TO AREA ($writeArea;$pictArea->)
	Else 
		$vb_Blob:=WR_MakeDummyText 
		WR BLOB TO AREA ($writeArea;$vb_Blob)
	End if 
End if 

Method Write_AreaToBlob stores the WR doc in blob:

C_LONGINT($1;$writeArea)
C_POINTER($2;$blobArea;$3)
C_BLOB($vb_Blob)
C_PICTURE($pict)
SET BLOB SIZE($vb_Blob;0)
$writeArea:=$1
$blobArea:=$2
If (Count parameters=3)
	$3->:=$pict
End if 
$vb_Blob:=WR Area to blob ($writeArea;1)
COMPRESS BLOB($vb_Blob;1)
$blobArea->:=$vb_Blob

Have fun Armin

Thanks to both Michael and Armin

Setting the frame to the header was a big missing piece of detail. Armin, thank you for the sample code. It helped me decipher what type of graphic actually was in place. In my WP documents they were inline graphics, so the selection of them required the WR Select and WR DELETE SELECTION commands to delete the PICT and then WR INSERT PICTURE to put in the new graphic.

Not sure that I would have ever figured this all out without this help. Thank you both again!