Create Many Layout in DWG

Discuss and ask questions about CAD VCL (Delphi and C++ Builder).

Moderators: SDS, support, admin

Post Reply
GuillaumeNATALI
Posts: 2
Joined: 02 Nov 2023, 13:09

Create Many Layout in DWG

Post by GuillaumeNATALI » 02 Nov 2023, 13:27

Hello everyone,

I am looking to create multiple Layouts in a DWG file. Unfortunately, the created file does not work correctly in DraftSight and causes an error in AutoCad.

The DraftSight error test shows this message:
Error:ACAD_LAYOUT Dictionary: Sheet (6A) associated with invalid BlockTableRecord should be Removed (Test:Invalid)

Here is the source code used to create a layout in "AddEntities" projet (provided by CADSoftTools) :

Code: Select all

{ function AddNewLayout

  Generates new paperspace block with new layout }

function AddNewLayout(const AConv: TsgDXFConverter; var ALayoutName: string;
  ASize: PF2DPoint; AGenerateViewPort: Boolean = True): TsgDXFBlock;
var
  I: Integer;
  vNewName: string;
  vPrintArea: TFRect;
begin
  // find unique paperspace block name
  I := 0;
  repeat
    vNewName := sPaperSpace;
    if I > 0 then
      vNewName := vNewName + IntToStr(I);
    Inc(I);
  until AConv.BlockByName(vNewName) = nil;
  // create new paperspace block
  Result := TsgDXFBlock.Create;
  // set paperspace block name
  Result.Name := vNewName;
  // create new layout and
  // set paperspace for new layout
  TsgDXFLayout.Create.PaperSpaceBlock := Result;
  // add paperspace block to the section
  AConv.Sections[csBlocks].AddEntity(Result);
  if AConv.LayoutByName(vNewName) = nil then
    vNewName := ALayoutName
  else
  begin
    // find unique layout name
    I := 1;
    repeat
      vNewName := sLayout + IntToStr(I);
      Inc(I);
    until AConv.LayoutByName(vNewName) = nil;
    ALayoutName := vNewName;
  end;
  // set layout name
  Result.Layout.Name := vNewName;
  // add layout to the section
  AConv.Sections[csLayouts].AddEntity(Result.Layout);
  if AGenerateViewPort then
  begin
    if ASize <> nil then
    begin
      TsgDXFLayout(Result.Layout).PlotSettings.PlotPaperSize := ASize^;
      TsgDXFConverterAccess(AConv).GenerateDisplayAndModelViewPort(
        TsgDXFLayout(Result.Layout),
        ASize^.X, ASize^.Y, 0);
    end
    else
    begin
      // reset plotsettings
      TsgDXFLayout(Result.Layout).PlotSettings.ResetForDefaultValue(nil); //??
      vPrintArea := TsgDXFLayout(Result.Layout).PlotSettings.PlotMarginsArea;
      // create new display viewport
      TsgDXFConverterAccess(AConv).GenerateDisplayAndModelViewPort(
        TsgDXFLayout(Result.Layout),
        vPrintArea.Right - vPrintArea.Left,
        Abs(vPrintArea.Top - vPrintArea.Bottom), 0);
    end;
  end;
  // loads new entities
  AConv.Loads(Result);
  AConv.Loads(Result.Layout);
end;


function TForm1.AddLayout(const cnstLayoutName:String; ASize: PF2DPoint): TsgDXFLayout;
var
  vLayoutName: string;
  vPaperSpaceBlock: TsgDXFBlock;
begin
  vLayoutName := cnstLayoutName;
  vPaperSpaceBlock := AddNewLayout(FCADFile.Converter, vLayoutName, ASize);
  Result := TsgDXFLayout(vPaperSpaceBlock.Layout);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  vSize: TF2DPoint;
begin
  if not CreateCADFile then
    Exit;
  AddLayer;
  AddLineType;
  AddStyle;
  AddText1;
  AddText2;
  AddMText;
  AddLine;
  AddPolyline1;
  AddPolyline2;
  AddLWPolyline;
  AddSpline;
  AddArc;
  AddCircle;
  AddSolid;
  AddDimension;
  AddHatch;
  AddImageEnt;
  AddInsert;
  FCADFile.GetExtents;

  vSize := MakeF2DPoint(297, 210);
  AddLayout(cnstLayoutTest, @vSize);
  //AddDisplayViewPort(297, 210, cnstLayoutTest);
  //AddModelViewPort(297, 210, cnstLayoutTest);

  vSize := MakeF2DPoint(210, 297);
  AddLayout(cnstLayoutTest2, @vSize);
  //AddDisplayViewPort(210, 297, cnstLayoutTest2);
  //AddModelViewPort( 210, 297, cnstLayoutTest2);

  vSize := MakeF2DPoint(420, 297);
  AddLayout(cnstLayoutTest3, @vSize);

  LoadLayouts;
  SetGraphic;
end;

Anyone have a solution?

support
Posts: 3271
Joined: 30 Mar 2005, 11:36
Contact:

Re: Create Many Layout in DWG

Post by support » 03 Nov 2023, 09:28

GuillaumeNATALI wrote:
02 Nov 2023, 13:27
Hello everyone,

I am looking to create multiple Layouts in a DWG file. Unfortunately, the created file does not work correctly in DraftSight and causes an error in AutoCad.

The DraftSight error test shows this message:
Error:ACAD_LAYOUT Dictionary: Sheet (6A) associated with invalid BlockTableRecord should be Removed (Test:Invalid)

Here is the source code used to create a layout in "AddEntities" projet (provided by CADSoftTools) :

Code: Select all

{ function AddNewLayout

  Generates new paperspace block with new layout }

function AddNewLayout(const AConv: TsgDXFConverter; var ALayoutName: string;
  ASize: PF2DPoint; AGenerateViewPort: Boolean = True): TsgDXFBlock;
var
  I: Integer;
  vNewName: string;
  vPrintArea: TFRect;
begin
  // find unique paperspace block name
  I := 0;
  repeat
    vNewName := sPaperSpace;
    if I > 0 then
      vNewName := vNewName + IntToStr(I);
    Inc(I);
  until AConv.BlockByName(vNewName) = nil;
  // create new paperspace block
  Result := TsgDXFBlock.Create;
  // set paperspace block name
  Result.Name := vNewName;
  // create new layout and
  // set paperspace for new layout
  TsgDXFLayout.Create.PaperSpaceBlock := Result;
  // add paperspace block to the section
  AConv.Sections[csBlocks].AddEntity(Result);
  if AConv.LayoutByName(vNewName) = nil then
    vNewName := ALayoutName
  else
  begin
    // find unique layout name
    I := 1;
    repeat
      vNewName := sLayout + IntToStr(I);
      Inc(I);
    until AConv.LayoutByName(vNewName) = nil;
    ALayoutName := vNewName;
  end;
  // set layout name
  Result.Layout.Name := vNewName;
  // add layout to the section
  AConv.Sections[csLayouts].AddEntity(Result.Layout);
  if AGenerateViewPort then
  begin
    if ASize <> nil then
    begin
      TsgDXFLayout(Result.Layout).PlotSettings.PlotPaperSize := ASize^;
      TsgDXFConverterAccess(AConv).GenerateDisplayAndModelViewPort(
        TsgDXFLayout(Result.Layout),
        ASize^.X, ASize^.Y, 0);
    end
    else
    begin
      // reset plotsettings
      TsgDXFLayout(Result.Layout).PlotSettings.ResetForDefaultValue(nil); //??
      vPrintArea := TsgDXFLayout(Result.Layout).PlotSettings.PlotMarginsArea;
      // create new display viewport
      TsgDXFConverterAccess(AConv).GenerateDisplayAndModelViewPort(
        TsgDXFLayout(Result.Layout),
        vPrintArea.Right - vPrintArea.Left,
        Abs(vPrintArea.Top - vPrintArea.Bottom), 0);
    end;
  end;
  // loads new entities
  AConv.Loads(Result);
  AConv.Loads(Result.Layout);
end;


function TForm1.AddLayout(const cnstLayoutName:String; ASize: PF2DPoint): TsgDXFLayout;
var
  vLayoutName: string;
  vPaperSpaceBlock: TsgDXFBlock;
begin
  vLayoutName := cnstLayoutName;
  vPaperSpaceBlock := AddNewLayout(FCADFile.Converter, vLayoutName, ASize);
  Result := TsgDXFLayout(vPaperSpaceBlock.Layout);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  vSize: TF2DPoint;
begin
  if not CreateCADFile then
    Exit;
  AddLayer;
  AddLineType;
  AddStyle;
  AddText1;
  AddText2;
  AddMText;
  AddLine;
  AddPolyline1;
  AddPolyline2;
  AddLWPolyline;
  AddSpline;
  AddArc;
  AddCircle;
  AddSolid;
  AddDimension;
  AddHatch;
  AddImageEnt;
  AddInsert;
  FCADFile.GetExtents;

  vSize := MakeF2DPoint(297, 210);
  AddLayout(cnstLayoutTest, @vSize);
  //AddDisplayViewPort(297, 210, cnstLayoutTest);
  //AddModelViewPort(297, 210, cnstLayoutTest);

  vSize := MakeF2DPoint(210, 297);
  AddLayout(cnstLayoutTest2, @vSize);
  //AddDisplayViewPort(210, 297, cnstLayoutTest2);
  //AddModelViewPort( 210, 297, cnstLayoutTest2);

  vSize := MakeF2DPoint(420, 297);
  AddLayout(cnstLayoutTest3, @vSize);

  LoadLayouts;
  SetGraphic;
end;

Anyone have a solution?
Hello,
We reviewed your code and it is not quite correct.
Please, have a look at the code example below:

Code: Select all

type
  TsgDXFConverterAccess = class(TsgDXFConverter);

{ function AddNewLayout
  Generates new paperspace block with new layout }
function AddNewLayout(const AConv: TsgDXFConverter; var ALayoutName: string;
  ASize: PF2DPoint; AGenerateViewPort: Boolean = True): TsgDXFBlock;
var
  I: Integer;
  vNewName: string;
  vPrintArea: TFRect;

  vLayout: TsgDXFLayout;
begin
  vLayout := TsgDXFLayout.Create;
  try
    if AConv.LayoutByName(vNewName) = nil then
      vNewName := ALayoutName
    else
    begin
      // find unique layout name
      I := 1;
      repeat
        vNewName := sLayout + IntToStr(I);
        Inc(I);
      until AConv.LayoutByName(vNewName) = nil;
    end;
    vLayout.Name := vNewName;
    AConv.AddLayout(vLayout);

    if AGenerateViewPort then
    begin
      if ASize <> nil then
      begin
        vLayout.PlotSettings.PlotPaperSize := ASize^;
        TsgDXFConverterAccess(AConv).GenerateDisplayAndModelViewPort(vLayout,
          ASize^.X, ASize^.Y, 0);
      end
      else
      begin
        // reset plotsettings
        vLayout.PlotSettings.ResetForDefaultValue(nil); //??
        vPrintArea := vLayout.PlotSettings.PlotMarginsArea;
        // create new display viewport
        TsgDXFConverterAccess(AConv).GenerateDisplayAndModelViewPort(vLayout,
          vPrintArea.Right - vPrintArea.Left,
          Abs(vPrintArea.Top - vPrintArea.Bottom), 0);
      end;
    end;

    AConv.Loads(vLayout);
    AConv.Loads(vLayout.PaperSpaceBlock);
    vLayout.PaperSpaceBlock.IsLoaded := False;
  finally
    Result := vLayout.PaperSpaceBlock;
  end;
end;

function TForm1.AddLine(const ALayoutName: string = ''): TsgDXFLine;
begin
  Result := TsgDXFLine.Create;
  Result.Point := MakeFPoint(80, 100, 0);
  Result.Point1 := MakeFPoint(150, 150, 0);
  Result.Color := clBlue;
  Result.Layer := FCADFile.Converter.LayerByName(cnstLayerName);
  Result.SetLType(FCADFile.Converter.LTypeByName(cnstLTypeName));
  Result.LineWeight := 0.7;
  if not AddEntityToLayout(Result, ALayoutName) then
  begin
    Result.Free;
    Result := nil;
  end;
end;

function TForm1.AddLayoutExt(const AName: String; ASize: PF2DPoint): TsgDXFLayout;
var
  vLayoutName: string;
  vPaperSpaceBlock: TsgDXFBlock;
begin
  vLayoutName := AName;
  vPaperSpaceBlock := AddNewLayout(FCADFile.Converter, vLayoutName, ASize);
  Result := TsgDXFLayout(vPaperSpaceBlock.Layout);
end;

////
const
  cnstLayoutTest1: string = 'Layout Test 1';
  cnstLayoutTest2: string = 'Layout Test 2';
  cnstLayoutTest3: string = 'Layout Test 3';

procedure TForm1.ButtonExt(Sender: TObject);
var
  vSize: TF2DPoint;
begin
  if not CreateCADFile then
    Exit;
  AddCircle;
  FCADFile.GetExtents;
  vSize := MakeF2DPoint(297, 210);
  AddLayoutExt(cnstLayoutTest1, @vSize);
  vSize := MakeF2DPoint(210, 297);
  AddLayoutExt(cnstLayoutTest2, @vSize);
  vSize := MakeF2DPoint(420, 297);
  AddLayoutExt(cnstLayoutTest3, @vSize);
  AddLine(cnstLayoutTest1).Color := clRed;
  AddLine(cnstLayoutTest2).Color := clBlue;
  AddLine(cnstLayoutTest3).Color := clGreen;
  LoadLayouts;
  SetGraphic;
end;

procedure TForm1.LoadLayouts;
var
  I: Integer;
begin
  if not Assigned(FCADFile) then
    Exit;
  for I := 0 to FCADFile.Converter.LayoutsCount - 1 do
    FCADFile.Converter.Loads(FCADFile.Converter.Layouts[I]);
end;
Best regards,
Catherine.
Technical Support E-mail: support@cadsofttools.com
Chat support on Skype: cadsofttools.support

GuillaumeNATALI
Posts: 2
Joined: 02 Nov 2023, 13:09

Re: Create Many Layout in DWG

Post by GuillaumeNATALI » 03 Nov 2023, 13:15

Thanks for your message, but the problem persists in Autocad 2008

Image
Image

support
Posts: 3271
Joined: 30 Mar 2005, 11:36
Contact:

Re: Create Many Layout in DWG

Post by support » 06 Nov 2023, 12:59

GuillaumeNATALI wrote:
03 Nov 2023, 13:15
Thanks for your message, but the problem persists in Autocad 2008

Image
Image
Thank you for the detailed description. Now our CAD VCL support team is working on your question.
I will post a reply when I got the feedback from the team.
Best regards,
Catherine.
Technical Support E-mail: support@cadsofttools.com
Chat support on Skype: cadsofttools.support

Post Reply