Hello Mikhail,
thanks a lot for your help!
I inserted your code into my project. Now the dwg can be saved without any errors. Unfortunately the values are not changed in the saved dwg.
Here is the code of my project. I hope that you can help me getting my problem solved.
Button1: open a dwg file and reading the values of all attributes
Button3: changing the value in Edit3 to the selected attribute and saving the dwg file
edit1: shows the selected block name (selected by clicking into the StringGrid)
edit2: shows the selected attribute name (selected by clicking into the StringGrid)
edit3: there the new value can be edited
Code: Select all
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Grids, CADImage, DXFConv, sgConsts, CADToDWG, DXF, DWG;
type
TForm1 = class(TForm)
Button1: TButton;
Button3: TButton;
StringGrid1: TStringGrid;
Edit1: TEdit;
Edit2: TEdit;
Edit3: TEdit;
OpenDialog1: TOpenDialog;
SaveDialog1: TSaveDialog;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
Label5: TLabel;
Label6: TLabel;
Label7: TLabel;
procedure Button1Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure StringGrid1SelectCell(Sender: TObject; ACol, ARow: Integer;
var CanSelect: Boolean);
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;
var
Form1: TForm1;
vDrawing: TsgCADImage; // a class for reading all the supported formats // global variable for keeping the file loaded in memory
implementation
{$R *.dfm}
procedure ChangeBlockAttribute(ACADImage: TsgCADImage; const ABlockName, AttribName, ANewValue: string);
var
I: Integer;
vDXFBlock: TsgDXFBlock;
vDXFAttdef: TsgDXFAttdef;
begin
if not Assigned(ACADImage) or (ABlockName = '')
then showmessage('Fehler');
vDXFBlock := ACADImage.Converter.BlockByName(ABlockName);
if Assigned(vDXFBlock) then
for I := 0 to vDXFBlock.Count - 1 do
begin
if (vDXFBlock.Entities[I].EntType = ceAttdef) then
begin
vDXFAttdef := vDXFBlock.Entities[I] as TsgDXFAttdef;
if (vDXFAttdef.Tag = AttribName) then
begin
vDXFAttdef.Value := ANewValue;
ACADImage.Converter.Loads(vDXFAttdef);
ACADImage.Converter.Loads(vDXFBlock);
Break;
end;
end;
end;
end;
procedure SaveToDWGFile(ACADImage: TsgCADImage; AFileName: string);
var
vCADtoDWG: TsgCADtoDWG;
begin
if not Assigned(ACADImage) then Exit;
vCADtoDWG := TsgCADtoDWG.Create(ACADImage);
try
vCADtoDWG.SaveToFile(AFileName);
finally
vCADtoDWG.Free;
end;
end;
// Open a DWG file an reading the attributes and values
procedure TForm1.Button1Click(Sender: TObject);
const
Exts: array[0..1] of string = ( '.dxf', '.dwg');
var
I, J, K, spalte, reihe: Integer;
vFileExt: string;
//vDrawing: TsgCADImage; // disabled for keeping the file loaded in memory, vDrawing is global variable
// An insert is a block reference. Several inserts can reference to the same block.
vInsert: TsgDXFInsert;
begin
if not OpenDialog1.Execute
then Exit;
for reihe:= StringGrid1.RowCount-1 downto 0 do // clearing the StringGrid if "open"-Button is pressed again
begin
for spalte:= StringGrid1.ColCount-1 downto 0 do
begin
StringGrid1.Cells[spalte, reihe]:= '';
end;
end;
StringGrid1.RowCount:= 1;
vFileExt := ExtractFileExt(LowerCase(OpenDialog1.FileName));
// Create an instance of TsgCADImage descendant depending on a file extension
case StrIndex(vFileExt, Exts) of
0: vDrawing := TsgCADdxfImage.Create; // for DXF files
1: vDrawing := TsgDWGImage.Create; // for DWG files
end;
vDrawing.LoadFromFile(OpenDialog1.FileName);
// Set a default layout as the current
vDrawing.CurrentLayout := vDrawing.Layouts[vDrawing.Converter.DefaultlayoutIndex];
K := 0;
StringGrid1.RowCount:= 1;
StringGrid1.Cells[0,0]:= 'Block Name';
StringGrid1.Cells[1,0]:= 'Attribut Name';
StringGrid1.Cells[2,0]:= 'Attribut aktueller Wert';
StringGrid1.Cells[3,0]:= 'Attribut neuer Wert';
// Searching entities in the current layout of the drawing
for I := 0 to vDrawing.CurrentLayout.Count - 1 do
begin
if vDrawing.CurrentLayout.Entities[I].EntType = ceInsert then
begin
vInsert := TsgDXFInsert(vDrawing.CurrentLayout.Entities[I]);
for J := 0 to vInsert.Attribs.Count - 1 do
begin
StringGrid1.RowCount:= StringGrid1.RowCount+1;
StringGrid1.Cells[0,K+J+1]:= vInsert.Block.Name;
StringGrid1.Cells[1,K+J+1]:= TsgDXFAttrib(vInsert.Attribs[J]).Tag;
StringGrid1.Cells[2,K+J+1]:= TsgDXFAttrib(vInsert.Attribs[J]).Value;
end;
K := K + vInsert.Attribs.Count;
end;
end;
//vDrawing.Free; // I disabled this line for keeping the drawing loaded in memory
Label2.Caption:= IntToStr(StringGrid1.RowCount-1);
Label3.Caption:= ExtractFileName(OpenDialog1.FileName);
end;
// Overwrite old values of attributes and saving the DWG file
procedure TForm1.Button3Click(Sender: TObject);
begin
if not SaveDialog1.Execute
then Exit;
ChangeBlockAttribute(vDrawing, edit1.text, edit2.text, edit3.Text); // all edit fields only for testing
SaveToDWGFile(vDrawing, SaveDialog1.FileName);
vDrawing.Free; // keeping the file loaded in memory
end;
// clicking on a cell takes the values to edit1 (Block name), and edit2 (Attribute Name)
procedure TForm1.StringGrid1SelectCell(Sender: TObject; ACol,
ARow: Integer; var CanSelect: Boolean);
begin
label7.Caption:= 'Zeile: '+IntToStr(ARow)+' / Spalte: '+intToStr(ACol);
Edit1.Text:= StringGrid1.Cells[0,ARow];
Edit2.Text:= StringGrid1.Cells[1,ARow];
end;
end.
THANKS A LOT FOR YOUR HELP!