.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

PLOTDATE field value updates via PLOT but not when plotted via API

11 REPLIES 11
SOLVED
Reply
Message 1 of 12
MarkSanchezSPEC
1459 Views, 11 Replies

PLOTDATE field value updates via PLOT but not when plotted via API

A client has specified that we include a "PlotDate" field in lieu of regular attribute in their title block.  This is formatted to contain, what else, but the date and time.

 

When our users enter the PLOT command, this field gets automatically updated to the current date and time, resulting in a plot with a plot stamp.

 

However, when we use our custom Batch Plot utility (VB.NET API), the drawings get plotted but the PlotDate field does NOT get updated.  I have found that fields of this type do not get updated via events like other fields, but rather when you call the UPDATEFIELD command.  However, the PLOT command itself must be doing something similar, as evidenced by the fact that the value of the field changes upon each PLOT.

 

How would I go about "updating/refreshing" a "PlotDate" field when plotting a file via the API?

11 REPLIES 11
Message 2 of 12

Hello Mark,

 

Here is a sample code to plot to PDF and the sample AutoCAD 2013 drawing that I am using which has a PlotDate field. The code to do the plotting is mostly from Kean's blog post.

After the plotting using this command, the field does get updated. Can you please see how this differs from what you are trying ?

 

[CommandMethod("GenPdf")]
public void GenPdf()
{
    try
    {
        PlotExtents("DWG To PDF.pc3", "ISO_expand_A4_(210.00_x_297.00_MM)", "monochrome.ctb", @"C:\Temp\Test.pdf");
    }
    catch (System.Exception e)
    {
        e.GetBaseException().ToString();
    }
}

// Plotting progress based on 
// http://through-the-interface.typepad.com/through_the_interface/2007/09/driving-a-multi.html
static public void PlotExtents(string printer, string format, string styleSheet, string pdfFilePath)
{
    try
    {
        Document doc = Application.DocumentManager.MdiActiveDocument;
        Editor ed = doc.Editor;
        Database db = doc.Database;

        using (Transaction tr = db.TransactionManager.StartTransaction())
        {
            BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForRead);
            Layout lo = (Layout)tr.GetObject(btr.LayoutId, OpenMode.ForRead);

            PlotInfo pi = new PlotInfo();
            pi.Layout = btr.LayoutId;

            PlotSettings ps = new PlotSettings(lo.ModelType);
            PlotConfigInfo pci = new PlotConfigInfo();

            ps.CopyFrom(lo);
            ps.PlotPlotStyles = true;

            PlotSettingsValidator psv = PlotSettingsValidator.Current;
            psv.SetStdScaleType(ps, StdScaleType.ScaleToFit);
            psv.SetDefaultPlotConfig(ps);

            psv.SetPlotType(ps, Autodesk.AutoCAD.DatabaseServices.PlotType.Extents);
            psv.SetUseStandardScale(ps, true);
            psv.SetPlotCentered(ps, true);
            psv.SetStdScaleType(ps, StdScaleType.ScaleToFit);


            ////PS-PlotRotation
            Extents2d extent2d = ps.PlotPaperMargins;
            if (extent2d.MaxPoint.Y > extent2d.MaxPoint.X)
            {
                psv.SetPlotRotation(ps, PlotRotation.Degrees000);
            }
            else
            {
                psv.SetPlotRotation(ps, PlotRotation.Degrees090);
            }

            try
            {
                psv.SetPlotConfigurationName(ps, printer, null);
                psv.SetPlotConfigurationName(ps, printer, format);
                psv.SetPlotPaperUnits(ps, PlotPaperUnit.Millimeters);
            }
            catch (System.Exception e)
            {
                e.GetBaseException().ToString();
            }

            psv.GetCanonicalMediaNameList(ps);
            pi.OverrideSettings = ps;

            PlotInfoValidator piv = new PlotInfoValidator();
            piv.MediaMatchingPolicy = MatchingPolicy.MatchEnabled;
            piv.Validate(pi);

            if (PlotFactory.ProcessPlotState == ProcessPlotState.NotPlotting)
            {
                using (PlotEngine pe = PlotFactory.CreatePublishEngine())
                {
                    PlotProgressDialog ppd = new PlotProgressDialog(false, 1, true);
                    using (ppd)
                    {
                        ppd.set_PlotMsgString(PlotMessageIndex.DialogTitle, "Plot Progress");
                        ppd.set_PlotMsgString(PlotMessageIndex.CancelJobButtonMessage, "Cancel Job");
                        ppd.set_PlotMsgString(PlotMessageIndex.CancelSheetButtonMessage, "Cancel Sheet");
                        ppd.set_PlotMsgString(PlotMessageIndex.SheetSetProgressCaption, "Sheet Set Progress");
                        ppd.set_PlotMsgString(PlotMessageIndex.SheetProgressCaption, "Sheet Progress");

                        ppd.LowerPlotProgressRange = 0;
                        ppd.UpperPlotProgressRange = 100;
                        ppd.PlotProgressPos = 0;

                        ppd.OnBeginPlot();
                        ppd.IsVisible = true;
                        ppd.OnBeginPlot();
                        ppd.IsVisible = true;
                        pe.BeginPlot(ppd, null);

                        pe.BeginDocument(pi, doc.Name, null, 1, true, pdfFilePath);

                        ppd.OnBeginSheet();
                        ppd.LowerSheetProgressRange = 0;
                        ppd.UpperSheetProgressRange = 100;
                        ppd.SheetProgressPos = 0;

                        PlotPageInfo ppi = new PlotPageInfo();
                        pe.BeginPage(ppi, pi, true, null);
                        pe.BeginGenerateGraphics(null);
                        ppd.SheetProgressPos = 50;
                        pe.EndGenerateGraphics(null);

                        pe.EndPage(null);
                        ppd.SheetProgressPos = 100;
                        ppd.OnEndSheet();

                        pe.EndDocument(null);

                        ppd.PlotProgressPos = 100;
                        ppd.OnEndPlot();

                        pe.EndPlot(null);
                    }
                }
            }
            else
            {
                ed.WriteMessage("\nCannot plot. System is busy plotting another one.");
            }

            tr.Commit();
        }
    }
    catch (System.Exception e)
    {
        // Display the error message here.
    }
}
}

 

 

 



Balaji
Developer Technical Services
Autodesk Developer Network

Message 3 of 12

Balaji,
I too originally got my code from Keans blog and have tweaked it to my use.
There were only a few lines from your post that I did not have in mine so I added them in the following manner:

1. Added 1st missing line
2. Test plotted my drawing - Bad results
3. Added 2nd missing line, leaving 1st line
4. Test plotted my drawing - Bad results
5. etc.

Even with all the missing lines added, I could not produce output where the field updated.
I was beginning to think that maybe it was an issue with my own drawing but everytime I issue the PLOT command in it, the field updates.

Next I turned my attention to your posted file (Test.dwg)
The first thing I had to do though was save it down to 2010 format using DWG TrueView/DWG Convert.
My post on the subscription site notes that we use the 2012 Infrastructure Suite.

Once I did that, I first used my original code to plot it out in Civil 2012 and once again the field did not update.
I then re-applied the missing lines from your post and re-plotted, but once again the field did not update.

This leads me to believe that perhaps it is an issue with 2012 that was fixed in 2013?
Can you try creating a similar drawing in 2012 (2010 format) then test your API code on it?

Thanks

Mark

Message 4 of 12

You create Batch Plot utility. I will ask three naive question.
1. Do you switch WorkingDatabase to the Database which plotting?
2. Do you save Database after plotting?

3. Code of Balaji (as is without your's changes) working as expected or no with AutoCAD 2012?

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

Message 5 of 12

Update: It works in 2012 with the 2010 format.  I just tested another app I have that produces single plots of the current drawing - It is a sort of simplified version of the PLOT command for use mainly by our non-CAD staff.  Plotting Balaji's drawing with it just produced a plot with the PlotDate field updated.

 

I am going to compare this code carefully with my Batch Plot code.

 

Your comment regarding WorkingDatabase is resonating in my mind - I am not setting this currently in the BatchPlot nor the app mentioned above, but it DOES make sense to do so while in batch mode...will re-post efforts.

 

Thanks

Message 6 of 12

I compared the code of each app and they are a match, which is what I expected because I built the BatchPlot app off of the other one.

I really think this is an issue with the WorkingDatabase and the "Batch" nature of my app.
I can't post all my code but here is what I think is relevant:

'This is sub that loops and processes each selected drawing:

 

Private Sub MySub()
    Dim dwg As Document = Nothing
    For Each dwgFile In files
        'open the drawing
        dwg = Application.DocumentManager.Open(dwgFile, True)

'--TRIED THIS LINE WITHOUT SUCCESS
        'HostApplicationServices.WorkingDatabase = dwg.Database

'--TRIED THIS LINE WITHOUT SUCCESS
        'Application.DocumentManager.MdiActiveDocument = dwg		

	MyPlottingFunction()

	dwg.CloseAndDiscard()
    Next
End Sub

 This is the function that handles the plotting:

 

Private Function MyPlottingFunction()
    Try
'--HAVE CONFIRMED HERE VIA db.FileName PROPERTY THAT WorkingDatabase IS SET TO CURRENTLY OPEN/ACTIVE DRAWING
        Using db As Database = HostApplicationServices.WorkingDatabase	
            Using tr As Transaction = db.TransactionManager.StartTransaction

                Dim btr As BlockTableRecord = tr.GetObject(db.CurrentSpaceId, OpenMode.ForRead)
                Dim objLayout As Layout = tr.GetObject(btr.LayoutId, OpenMode.ForRead)
                Dim pi As PlotInfo = New PlotInfo
                pi.Layout = btr.LayoutId

	        ...
                ...
	    End Using
	End Using
    Catch
        ...
    End Try
End Function

 In the "MyPlottingFunction" above I even tried this:

 

Dim db As Database = dwg.Database     'dwg PASSED IN AS BYREF PARAM (MY ORIG CODE)

 

And this:

 

HostApplicationServices.WorkingDatabase = db    'db PASSED IN AS BYREF PARAM

 

I once struggeled with a batch application that was not setting my variables to the "active" drawing and found the solution was to add the Session attribute to the CommandMethod like this:

 

    <CommandMethod("BP", CommandFlags.Session)> _
        Public Sub Main()

 

I have had this setting in my BatchPlot app from the begining however.  Stumped!

Message 7 of 12

Hello Mark,

 

I have tried making the command run in the "Session" context, but it still worked ok in AutoCAD 2012.

 

Have you tried not opening the drawing using "Application.DocumentManager.Open(dwgFile, True)" and having your code plot the drawing which is already open in the editor ?

 

Sorry, I am not sure what else might be causing this issue.

You may try isolating chunks of your code at a time and narrow down on the cause.



Balaji
Developer Technical Services
Autodesk Developer Network

Message 8 of 12


@Anonymous wrote:
...
dwg.CloseAndDiscard()
...

My second question was: 2. Do you save Database after plotting?
You DO NOT save dwg-file after ploting and that is why PLOTDATE is not changed.

 

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

Message 9 of 12

Saving would not work.  The application is a batch plotter only, which never makes any changes to a drawing.

 

In any case, I don't completely agree.  We are not trying to save the updated "PlotDate" field in the drawing itself.  We only wish to have the current date/time show up in the output plot (hard copy or pdf).  This is what happens when we PLOT a drawing - the drawing could be saved (or not), just as long as the output contains the date/time of the plotting operation.  Sorry for the confusion.

 

 

Message 10 of 12

using System;
using System.Collections.Generic;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.PlottingServices;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;

[assembly: CommandClass(typeof(Rivilis.PDFPlot))]

namespace Rivilis
{

  public class PDFPlot
  {
    [CommandMethod("GenPdf", CommandFlags.Session)]
    public void GenPdf()
    {
      string[] files = { "C:\\FieldPlot1.dwg", "C:\\FieldPlot2.dwg", "C:\\FieldPlot3.dwg" }; // Test files with PLOTDATE field
      object oldBgPlot = Application.GetSystemVariable("BACKGROUNDPLOT");
      Application.SetSystemVariable("BACKGROUNDPLOT", 0);
      Document oldDoc = Application.DocumentManager.MdiActiveDocument;
      Database oldDb = HostApplicationServices.WorkingDatabase;
      try {
        foreach (string file in files) {
          Document doc = Application.DocumentManager.Open(file, true);
          Application.DocumentManager.MdiActiveDocument = doc;
          HostApplicationServices.WorkingDatabase = doc.Database;
          using (DocumentLock docloc = doc.LockDocument()) {
            PlotExtents("DWG To PDF.pc3", "ISO_expand_A4_(210.00_x_297.00_MM)", "monochrome.ctb", file + ".pdf");
          }
          doc.CloseAndDiscard();
        }
        Application.DocumentManager.MdiActiveDocument = oldDoc;
        HostApplicationServices.WorkingDatabase = oldDb;
        Application.SetSystemVariable("BACKGROUNDPLOT", oldBgPlot);
      }
      catch (System.Exception e) {
        System.Windows.Forms.MessageBox.Show(
          e.ToString(),
          "Error",
          System.Windows.Forms.MessageBoxButtons.OK,
          System.Windows.Forms.MessageBoxIcon.Error);
      }
    }

    // Plotting progress based on 
    // http://through-the-interface.typepad.com/through_the_interface/2007/09/driving-a-multi.html
    static public void PlotExtents(string printer, string format, string styleSheet, string pdfFilePath)
    {

      Document doc = Application.DocumentManager.MdiActiveDocument;
      Editor ed = doc.Editor;
      Database db = doc.Database;
      try {
        using (Transaction tr = db.TransactionManager.StartTransaction()) {
          BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForRead);
          Layout lo = (Layout)tr.GetObject(btr.LayoutId, OpenMode.ForRead);

          PlotInfo pi = new PlotInfo();
          pi.Layout = btr.LayoutId;

          PlotSettings ps = new PlotSettings(lo.ModelType);
          PlotConfigInfo pci = new PlotConfigInfo();

          ps.CopyFrom(lo);
          ps.PlotPlotStyles = true;

          PlotSettingsValidator psv = PlotSettingsValidator.Current;
          psv.SetStdScaleType(ps, StdScaleType.ScaleToFit);
          psv.SetDefaultPlotConfig(ps);

          psv.SetPlotType(ps, Autodesk.AutoCAD.DatabaseServices.PlotType.Extents);
          psv.SetUseStandardScale(ps, true);
          psv.SetPlotCentered(ps, true);
          psv.SetStdScaleType(ps, StdScaleType.ScaleToFit);


          ////PS-PlotRotation
          Extents2d extent2d = ps.PlotPaperMargins;
          if (extent2d.MaxPoint.Y > extent2d.MaxPoint.X) {
            psv.SetPlotRotation(ps, PlotRotation.Degrees000);
          }
          else {
            psv.SetPlotRotation(ps, PlotRotation.Degrees090);
          }

          try {
            psv.SetPlotConfigurationName(ps, printer, null);
            psv.SetPlotConfigurationName(ps, printer, format);
            psv.SetPlotPaperUnits(ps, PlotPaperUnit.Millimeters);
          }
          catch (System.Exception e) {
            e.GetBaseException().ToString();
          }

          psv.GetCanonicalMediaNameList(ps);
          pi.OverrideSettings = ps;

          PlotInfoValidator piv = new PlotInfoValidator();
          piv.MediaMatchingPolicy = MatchingPolicy.MatchEnabled;
          piv.Validate(pi);

          if (PlotFactory.ProcessPlotState == ProcessPlotState.NotPlotting) {
            using (PlotEngine pe = PlotFactory.CreatePublishEngine()) {
              PlotProgressDialog ppd = new PlotProgressDialog(false, 1, true);
              using (ppd) {
                ppd.set_PlotMsgString(PlotMessageIndex.DialogTitle, "Plot Progress");
                ppd.set_PlotMsgString(PlotMessageIndex.CancelJobButtonMessage, "Cancel Job");
                ppd.set_PlotMsgString(PlotMessageIndex.CancelSheetButtonMessage, "Cancel Sheet");
                ppd.set_PlotMsgString(PlotMessageIndex.SheetSetProgressCaption, "Sheet Set Progress");
                ppd.set_PlotMsgString(PlotMessageIndex.SheetProgressCaption, "Sheet Progress");

                ppd.LowerPlotProgressRange = 0;
                ppd.UpperPlotProgressRange = 100;
                ppd.PlotProgressPos = 0;

                ppd.OnBeginPlot();
                ppd.IsVisible = true;
                ppd.OnBeginPlot();
                ppd.IsVisible = true;
                pe.BeginPlot(ppd, null);

                pe.BeginDocument(pi, doc.Name, null, 1, true, pdfFilePath);

                ppd.OnBeginSheet();
                ppd.LowerSheetProgressRange = 0;
                ppd.UpperSheetProgressRange = 100;
                ppd.SheetProgressPos = 0;

                PlotPageInfo ppi = new PlotPageInfo();
                pe.BeginPage(ppi, pi, true, null);
                pe.BeginGenerateGraphics(null);
                ppd.SheetProgressPos = 50;
                pe.EndGenerateGraphics(null);

                pe.EndPage(null);
                ppd.SheetProgressPos = 100;
                ppd.OnEndSheet();

                pe.EndDocument(null);

                ppd.PlotProgressPos = 100;
                ppd.OnEndPlot();

                pe.EndPlot(null);
              }
            }
          }
          else {
            ed.WriteMessage("\nCannot plot. System is busy plotting another one.");
          }

          tr.Commit();
        }
      }
      catch (System.Exception e) {
        // Display the error message here.
        System.Windows.Forms.MessageBox.Show(
          e.ToString(),
          "Error",
          System.Windows.Forms.MessageBoxButtons.OK,
          System.Windows.Forms.MessageBoxIcon.Error);
      }
    }
  }
}

 This code was tested with AutoCAD 2012 and seems to work as expected.

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

Message 11 of 12

That's it!

Placing the call to my plotting function in a DocumentLock Using statement allowed the PlotDate field to update.

 

Using dl As DocumentLock = doc.LockDocument
MyPlottingFunction()
End Using


Thank you Alexandar!  I owe you a drink if you come out to AU or the ADN conference in Las Vegas this year.

 

 

Message 12 of 12


@Anonymous wrote:

That's it!

Placing the call to my plotting function in a DocumentLock Using statement allowed the PlotDate field to update.


An interesting side effect. Usually DocumentLock need to use only when we change something in the Database. In this case, we are not changing anything in the Database, but the change is due to the recalculation of of fields (including PLOTDATE)

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost