在调用cad的.net api打印pdf文件效率很低
大神们,你们好,我在调用cad的.net api生成pdf文档的时候,效率很低具体需求
比如在一张图纸上我指定了4个区域,我想把这4个区域打印成4个pdf文件,如文件1,文件2,文件3,和文件4,生成这4个文件一般需要6分钟左右,效率很低下,测试的cad图纸不复杂,请问大神我问题出在哪,
下面贴上我的打印代码
Document acDoc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
Database acCurDb = acDoc.Database;
Transaction acTrans = acCurDb.TransactionManager.StartTransaction();
try
{
using (acTrans)
{
int flag = 0;
//获取当前布局管理器变量
LayoutManager acLayoutMgr = LayoutManager.Current;
//获取当前布局变量
Layout acLayout = (Layout)acTrans.GetObject(acLayoutMgr.GetLayoutId(acLayoutMgr.CurrentLayout), OpenMode.ForRead);
//Layout acLayout = (Layout)acTrans.GetObject(acLayoutMgr.GetLayoutId(acLayoutMgr.CurrentLayout), OpenMode.ForWrite);
//获取当前布局的打印信息
PlotInfo acPlInfo = new PlotInfo()
{
Layout = acLayout.ObjectId
};
PlotSettings acPlSet = new PlotSettings(acLayout.ModelType);
acPlSet.CopyFrom(acLayout);
//着色打印选项,设置按线框进行打印
acPlSet.ShadePlot = PlotSettingsShadePlotType.Wireframe;
PlotSettingsValidator acPlSetVdr = PlotSettingsValidator.Current;
//打印比例
//用户标准打印
acPlSetVdr.SetUseStandardScale(acPlSet, true);
acPlSetVdr.SetStdScaleType(acPlSet, StdScaleType.ScaleToFit);
//居中打印
acPlSetVdr.SetPlotCentered(acPlSet, true);
//调用GetPlotStyleSheetList之后才可以使用SetCurrentStyleSheet
System.Collections.Specialized.StringCollection sc = acPlSetVdr.GetPlotStyleSheetList();
//设置打印样式表
acPlSetVdr.SetCurrentStyleSheet(acPlSet, "测试打印样式1.ctb");
PlotProgressDialog acPlProgDlg = new PlotProgressDialog(false, entitylist.Count, true);
foreach (FrameAttributeExtend frame in entitylist)
{
if (!Directory.Exists(directory))
Directory.CreateDirectory(directory);
flag++;
//比例
string entityscale = frame.Scale;
//横竖
string vertial = frame.IsVertial;
//图片索引
string picindex = frame.ImageIndex;
string imagename = "";
if (frame.ImageType == 0)
{
imagename = string.Format("1-{0}-{1}-{2}.pdf", entityscale, vertial, picindex);
totalflatimage = directory + imagename;
}
else
{
imagename = string.Format("2-{0}-{1}-{2}.pdf", entityscale, vertial, picindex);
imagelist.Add(directory + imagename);
}
//打印设备和图纸
if (vertial == "0")
{
//横向
acPlSetVdr.SetPlotConfigurationName(acPlSet, "DWG To PDF.pc3", "ISO_expand_A4_(297.00_x_210.00_mm)");
acPlSetVdr.SetPlotRotation(acPlSet, PlotRotation.Degrees000);
}
else
{
//竖向
acPlSetVdr.SetPlotConfigurationName(acPlSet, "DWG To PDF.pc3", "ISO_expand_A4_(210.00_x_297.00_mm)");
acPlSetVdr.SetPlotRotation(acPlSet, PlotRotation.Degrees000);
}
//设置是否使用打印样式
acPlSet.ShowPlotStyles = true;
//设置打印区域
Extents3d extents3d = frame.Extent;
//单位是米时
double h = double.Parse(entityscale) * 6;
double x = extents3d.MinPoint.X + unit * 2;
double y = extents3d.MaxPoint.Y + h + unit;
if (unit == 1)
{
x = extents3d.MinPoint.X + unit * 1;
y = extents3d.MaxPoint.Y + double.Parse(entityscale) / 250 + unit * 2;
}
Extents2d E2d = new Extents2d(x, extents3d.MinPoint.Y, extents3d.MaxPoint.X, y);
acPlSetVdr.SetPlotWindowArea(acPlSet, E2d);
acPlSetVdr.SetPlotType(acPlSet, Autodesk.AutoCAD.DatabaseServices.PlotType.Window);
//重载和保存打印信息
acPlInfo.OverrideSettings = acPlSet;
//验证打印信息设置,看是否有误
PlotInfoValidator acPlInfoVdr = new PlotInfoValidator();
acPlInfoVdr.MediaMatchingPolicy = MatchingPolicy.MatchEnabled;
acPlInfoVdr.Validate(acPlInfo);
while (PlotFactory.ProcessPlotState != Autodesk.AutoCAD.PlottingServices.ProcessPlotState.NotPlotting)
continue;
PlotEngine acPlEng = PlotFactory.CreatePublishEngine();
#region BackUpCode
acPlProgDlg.set_PlotMsgString(PlotMessageIndex.DialogTitle, "图片输出");
acPlProgDlg.set_PlotMsgString(PlotMessageIndex.CancelSheetButtonMessage, "取消输出");
acPlProgDlg.set_PlotMsgString(PlotMessageIndex.SheetProgressCaption, "输出进度");
acPlProgDlg.LowerPlotProgressRange = 0;
acPlProgDlg.UpperPlotProgressRange = 100;
acPlProgDlg.PlotProgressPos = 0;
acPlProgDlg.OnBeginPlot();
acPlProgDlg.IsVisible = true;
acPlEng.BeginPlot(acPlProgDlg, null);
acPlEng.BeginDocument(acPlInfo, "", null, 1, true, directory + imagename);
acPlProgDlg.set_PlotMsgString(PlotMessageIndex.Status, string.Format("正在输出第{0}张", flag.ToString()));
acPlProgDlg.OnBeginSheet();
acPlProgDlg.LowerSheetProgressRange = 0;
acPlProgDlg.UpperSheetProgressRange = 100;
acPlProgDlg.SheetProgressPos = 0;
PlotPageInfo acPlPageInfo = new PlotPageInfo();
acPlEng.BeginPage(acPlPageInfo, acPlInfo, true, null);
acPlEng.BeginGenerateGraphics(null);
acPlEng.EndGenerateGraphics(null);
acPlEng.EndPage(null);
acPlProgDlg.SheetProgressPos = 100;
acPlProgDlg.OnEndSheet();
acPlEng.EndDocument(null);
acPlProgDlg.PlotProgressPos = 100;
acPlProgDlg.OnEndPlot();
acPlEng.EndPlot(null);
acPlEng.Dispose();
acPlEng.Destroy();
#endregion
//}
}
acPlProgDlg.Dispose();
acPlProgDlg.Destroy();
}
while (PlotFactory.ProcessPlotState != Autodesk.AutoCAD.PlottingServices.ProcessPlotState.NotPlotting)
continue;
//MessageBox.Show("打印完成!");
在while循环中,等待的时间最久,似乎一直在等cad的打印机工作状态重置,另外,能不能把这4页生成到1个pdf文件里面呢,这样是否能够对效率做一些优化?
求大神指导,谢谢了!
本帖最后由 mkhsj928 于 2017-10-20 15:13 编辑
/// <summary>
/// 多页打印/预览函数
/// </summary>
/// <param name="pe"></param>
/// <param name="isPreview"></param>
/// <param name="plotList"></param>
/// <param name="sheetNumIfPreview"></param>
/// <param name="layoutCount"></param>
/// <param name="plotDevice"></param>
/// <param name="plotCanonicalMeida"></param>
/// <param name="plotStyle"></param>
/// <param name="saveFileName"></param>
/// <returns></returns>
private static PreviewEndPlotStatus MultiPlotOrPreview(
PlotEngine pe,
bool isPreview,
Dictionary<Extents2d, ObjectId> plotList,
int sheetNumIfPreview,
int layoutCount,//布局总数
string plotDevice,
string plotCanonicalMeida,
string plotStyle,
string saveFileName
)
{
PreviewEndPlotStatus ret = PreviewEndPlotStatus.Cancel;
string DocName = mCommands.Doc.Name;
DocName = DocName.Substring(DocName.LastIndexOf("\\") + 1);
DocName = DocName.Substring(0, DocName.LastIndexOf("."));
#region 准备打印区域列表plotAreaList
Dictionary<Extents2d, ObjectId> plotAreaList = new Dictionary<Extents2d, ObjectId>();
if (isPreview && sheetNumIfPreview >= 0)
{
KeyValuePair<Extents2d, ObjectId> kv = plotList.ElementAt(sheetNumIfPreview);
plotAreaList.Add(kv.Key, kv.Value);//预览只能一个区域
}
else
{
plotAreaList = plotList;//打印全部区域
}
#endregion
using (Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.LockDocument())
{
try
{
using (PlotProgressDialog ppd = new PlotProgressDialog(isPreview, plotAreaList.Count, false))
{
#region 设置进度条显示信息
ppd.set_PlotMsgString(PlotMessageIndex.DialogTitle, "转换进度");
ppd.set_PlotMsgString(PlotMessageIndex.SheetProgressCaption, "本布局转换进度:__/__");
ppd.set_PlotMsgString(PlotMessageIndex.SheetSetProgressCaption, "总转换进度: __/__");
ppd.LowerPlotProgressRange = 0;
ppd.UpperPlotProgressRange = plotAreaList.Count;
//显示进度条对话框
ppd.OnBeginPlot();
ppd.IsVisible = true;
#endregion
int pageNum = 0;//布局打印页计数
int layoutPageNum = 0;//当前布局总打印页数(区域数)
int sheetNum = 0;//所有打印页计数(打印总区域数)
ObjectId layoutId = ObjectId.Null;//当前布局Id
Layout lo = null;
foreach (KeyValuePair<Extents2d, ObjectId> kv in plotAreaList)
{
if (kv.Value != layoutId)
{
layoutId = kv.Value;
lo = mFun.m_OpenEntity(layoutId) as Layout;
LayoutManager.Current.CurrentLayout = lo.LayoutName;//切换为当前布局,是否必须?!!
pageNum=0;//重置布局页计数
layoutPageNum = plotAreaList.Count(a => a.Value == layoutId);
ppd.LowerSheetProgressRange = 0;
ppd.UpperSheetProgressRange = layoutPageNum;
}
pageNum++;//布局页计数+1
sheetNum++;//总打印区域计数+1
ppd.set_PlotMsgString(PlotMessageIndex.SheetName, $"{DocName}-{lo.LayoutName}");//打印文件名-布局名
//设置打印配置参数
PlotInfo pi = SetPlotInfo(lo, kv.Key, plotDevice, plotCanonicalMeida, plotStyle,isPreview);
#region 启动打印
if (sheetNum == 1)
{
pe.BeginPlot(ppd, null);
pe.BeginDocument(
pi, //打印信息
mCommands.Doc.Name, //当前图纸名
null,
1, //打印份数
!isPreview, //是否打印至文件
isPreview ? "" : saveFileName //保存文件名
);
}
#endregion
#region 开始打印
ppd.OnBeginSheet();
ppd.SheetProgressPos = pageNum;
ppd.set_PlotMsgString(PlotMessageIndex.SheetProgressCaption, $"本布局转换进度:{pageNum}/{layoutPageNum}");
ppd.PlotProgressPos = sheetNum;
ppd.set_PlotMsgString(PlotMessageIndex.SheetSetProgressCaption, $"总转换进度:sheetNum}/{plotAreaList.Count}");
pe.BeginPage(
new PlotPageInfo(),
pi, //打印信息
sheetNum == plotAreaList.Count, //是否最后一页
null
);
pe.BeginGenerateGraphics(null);
pe.EndGenerateGraphics(null);
PreviewEndPlotInfo pepi = new PreviewEndPlotInfo();
pe.EndPage(pepi);//结束本页打印,返回预览状态
ret = pepi.Status;
#endregion
}
#region 结束打印
ppd.OnEndSheet();
pe.EndDocument(null);
ppd.OnEndPlot();
pe.EndPlot(null);
#endregion
}
}
catch (Autodesk.AutoCAD.Runtime.Exception e)
{
MessageBox.Show($"转换为单个PDF文档出错: {e.Message}!\n请选择【单幅分别保存】进行转换。", "转换出错", MessageBoxButtons.OK, MessageBoxIcon.Error);
ret = PreviewEndPlotStatus.Cancel;
}
}
return ret;
} /// <summary>
/// 打印预览
/// </summary>
/// <returns></returns>
public static bool Preview(
Dictionary<ObjectId, List<Extents2d>> plotAreaDict,
string plotDevice,
string plotCanonicalMeida,
string plotStyle,
string saveFileName,
bool isPlotSingle//是否每页单独保存
)
{
bool ret = false;
if (plotAreaDict.Count == 0) return true;
#region 准备打印区域列表 PlotList
Dictionary<Extents2d, ObjectId> PlotList = new Dictionary<Extents2d, ObjectId>();
foreach (KeyValuePair<ObjectId, List<Extents2d>> kv in plotAreaDict)
{
foreach (Extents2d plotArea in kv.Value)
{
PlotList.Add(plotArea, kv.Key);
}
}
#endregion
if (PlotFactory.ProcessPlotState == ProcessPlotState.NotPlotting)
{
#region 设置为前台打印
object BackGroundPlotVar = mFun.m_GetSystemVar("BACKGROUNDPLOT");
mFun.m_SetSystemVar("BACKGROUNDPLOT", 0);//一定要设置成0(前台打印),否则保存PDF文件中一个布局只会有一张图!!!!
#endregion
int sheetNum = 0;
bool isFinished = false;//预览是否结束
bool isReadyForPlot = false;//是否准备好打印
while (!isFinished)
{
PreviewEngineFlags flags = PreviewEngineFlags.Plot;
if (sheetNum > 0)
flags |= PreviewEngineFlags.PreviousSheet;
if (sheetNum < PlotList.Count - 1)
flags |= PreviewEngineFlags.NextSheet;
using (PlotEngine pe = PlotFactory.CreatePreviewEngine((int)flags))
{
PreviewEndPlotStatus stat = MultiPlotOrPreview(
pe, true, PlotList, sheetNum, plotAreaDict.Count,
plotDevice, plotCanonicalMeida, plotStyle, saveFileName
);
if (stat == PreviewEndPlotStatus.Next)
{
sheetNum++;
}
else if (stat == PreviewEndPlotStatus.Previous)
{
sheetNum--;
}
else if (stat == PreviewEndPlotStatus.Normal ||
stat == PreviewEndPlotStatus.Cancel)
{
isFinished = true;
}
else if (stat == PreviewEndPlotStatus.Plot)
{
isFinished = true;
isReadyForPlot = true;
ret = true;//结束
}
}
}
// If the plot button was used to exit the preview...
if (isReadyForPlot)
{
if (!isPlotSingle)
{
using (PlotEngine pe = PlotFactory.CreatePublishEngine())
{
PreviewEndPlotStatus stat = MultiPlotOrPreview(
pe, false, PlotList, -1, plotAreaDict.Count,
plotDevice, plotCanonicalMeida, plotStyle, saveFileName
);
ret = stat == PreviewEndPlotStatus.Cancel ? false : true;
}
}
else
{
#region 每页打印成一个PDF文件
foreach (KeyValuePair<ObjectId, List<Extents2d>> kv in plotAreaDict)
{
int i = 1;
foreach (Extents2d plotArea in kv.Value)
{
MYAPP.mPlot.PlotSinglePage(
kv.Key, plotArea, plotDevice, plotCanonicalMeida, plotStyle,
string.Format("{0}-{1}({2})", saveFileName,mLayout.GetLayoutName(kv.Key), i++));
}
}
#endregion
}
}
//恢复变量
mFun.m_SetSystemVar("BACKGROUNDPLOT", BackGroundPlotVar);
}
else
{
mCommands.m_ed.WriteMessage("\n其他打印正在进行中!");
}
return ret;
} /// <summary>
/// 设置打印信息
/// </summary>
/// <param name="layoutId">布局ID</param>
/// <param name="plotArea">该布局中的一个区域</param>
/// <param name="plotDevice">打印设备名</param>
/// <param name="plotCanonicalMeida">标准打印介质名</param>
/// <param name="plotStyle">打印样式</param>
/// <param name="isSinglePage">是否只打印单页</param>
/// <returns></returns>
private static PlotInfo SetPlotInfo(Layout lo, Extents2d plotArea,
string plotDevice, string plotCanonicalMeida, string plotStyle,bool isSinglePage)
{
PlotInfo pi = new PlotInfo();
pi.Layout = lo.Id;
//获取当前布局的打印信息
PlotSettings ps = new PlotSettings(lo.ModelType);//是否模型空间
ps.CopyFrom(lo);
//着色打印选项,设置按线框进行打印
ps.ShadePlot = PlotSettingsShadePlotType.Wireframe;
//获取当前打印设置校验器
PlotSettingsValidator psv = PlotSettingsValidator.Current;
#region 以下这些设置请不要改变顺序!!!
//以下2句顺序不能换!
psv.SetPlotWindowArea(ps, plotArea);//设置打印区域
psv.SetPlotType(ps, Autodesk.AutoCAD.DatabaseServices.PlotType.Window);//设置为窗口打印模式
//设置布满图纸打印
psv.SetUseStandardScale(ps, true);//需要?
psv.SetStdScaleType(ps, StdScaleType.ScaleToFit);//布满图纸
//设置居中打印
psv.SetPlotCentered(ps, true);
//设置打印样式
try
{
psv.SetCurrentStyleSheet(ps, plotStyle);//设置打印样式(笔宽等)(为什么有时会出错?PS:不能与原样式形同?!!!)
}
catch (Autodesk.AutoCAD.Runtime.Exception e)
{
MessageBox.Show(string.Format("{0}\n当前打印样式:{1}\n设置打印样式:{2}", e.Message, ps.CurrentStyleSheet, plotStyle), "设置打印样式出错");
}
//配置打印机和打印介质
psv.SetPlotConfigurationName(ps, plotDevice, plotCanonicalMeida);
psv.RefreshLists(ps);
//设置打印单位
try
{
psv.SetPlotPaperUnits(ps, PlotPaperUnit.Millimeters);//(为什么有时会出错?)
}
catch (Autodesk.AutoCAD.Runtime.Exception e)
{
MessageBox.Show(string.Format("{0}\n当前尺寸单位:{1}\n设置单位:{2}", e.Message, ps.PlotPaperUnits, PlotPaperUnit.Millimeters), "设置尺寸单位出错");
}
//设置旋转角度(打印到同一文档时必须设置为同一旋转角)
if (isSinglePage)
{
if ((plotArea.MaxPoint.X - plotArea.MinPoint.X) > (plotArea.MaxPoint.Y - plotArea.MinPoint.Y))
{
if (ps.PlotPaperSize.X > ps.PlotPaperSize.Y)
{
psv.SetPlotRotation(ps, PlotRotation.Degrees000);
}
else
{
psv.SetPlotRotation(ps, PlotRotation.Degrees090);
}
}
else
{
if (ps.PlotPaperSize.X > ps.PlotPaperSize.Y)
{
psv.SetPlotRotation(ps, PlotRotation.Degrees090);
}
else
{
psv.SetPlotRotation(ps, PlotRotation.Degrees000);
}
}
}
else
{
//多页打印必须设置为统一旋转角度(否则打印会出错,出错信息:eValidePlotInfo!特别注意!!!)
psv.SetPlotRotation(ps, PlotRotation.Degrees000);
}
#endregion
pi.OverrideSettings = ps;//将PlotSetting与PlotInfo关联
PlotInfoValidator piv = new PlotInfoValidator();
piv.MediaMatchingPolicy = MatchingPolicy.MatchEnabled;
piv.Validate(pi);//激活打印设置
ps.Dispose();
return pi;
} 大神们,你们在哪,求解答,谢谢啦! 4页生成一个文件的话 你可以考虑换个pdf打印机
我记得有个pdffac..(工厂?) 雪山飞狐_lzh 发表于 2016-3-1 11:38 static/image/common/back.gif
4页生成一个文件的话 你可以考虑换个pdf打印机
我记得有个pdffac..(工厂?)
PlotFactory么?
4页生不生成一个文件不是最重要的,我现在的问题是效率的问题
我用上面那个代码总共要花数分钟(取决于数量和图的负责度,比较简单的基本上都要上分钟了)
我的需求是把一个Extend2d范围内(即图框范围)内的东西打印到pdf图纸上
求大神指点,谢谢 本帖最后由 ps122hb 于 2016-3-7 08:23 编辑
_wtf 发表于 2016-3-1 16:23 static/image/common/back.gif
PlotFactory么?
4页生不生成一个文件不是最重要的,我现在的问题是效率的问题
我用上面那个代码总共要 ...
打印机 pdfFactory
你是在模型空间还是图纸空间打印?我的理解你好像在模型空间,但程序里应该是图纸空间,你再看看
ps122hb 发表于 2016-3-7 08:21 static/image/common/back.gif
打印机 pdfFactory
你是在模型空间还是图纸空间打印?我的理解你好像在模型空间,但程序里应该是图纸 ...
我是在图纸空间上打印的吧,取的是图纸上的坐标,然后按照区域来打印
pdffactory是必须要单独安装的吧
这样给客户相对来说不是特别方便 我今天试着写打印也和你一样的情况,非常慢,如果是直接用CAD的打印则很快 /// <summary>
/// 打印
/// </summary>
/// <param name="plotAreaDict"></param>
/// <param name="plotDevice"></param>
/// <param name="plotCanonicalMeida"></param>
/// <param name="plotStyle"></param>
/// <param name="saveFileName"></param>
/// <returns></returns>
public static bool Plot(
Dictionary<ObjectId, List<Extents2d>> plotAreaDict,
string plotDevice,
string plotCanonicalMeida,
string plotStyle,
string saveFileName
)
{
bool ret = true;
if (plotAreaDict.Count == 0) return true;
#region 准备打印区域列表 PlotList
Dictionary<Extents2d, ObjectId> PlotList = new Dictionary<Extents2d, ObjectId>();
foreach (KeyValuePair<ObjectId, List<Extents2d>> kv in plotAreaDict)
{
foreach (Extents2d plotArea in kv.Value)
{
PlotList.Add(plotArea, kv.Key);
}
}
#endregion
if (PlotFactory.ProcessPlotState == ProcessPlotState.NotPlotting)
{
#region 设置为前台打印
object BackGroundPlotVar = mFun.m_GetSystemVar("BACKGROUNDPLOT");
mFun.m_SetSystemVar("BACKGROUNDPLOT", 0);//一定要设置成0(前台打印),否则保存PDF文件中一个布局只会有一张图!!!!
#endregion
using (PlotEngine pe = PlotFactory.CreatePublishEngine())
{
PreviewEndPlotStatus stat = MultiPlotOrPreview(
pe, false, PlotList, -1, plotAreaDict.Count,
plotDevice, plotCanonicalMeida, plotStyle, saveFileName
);
ret = stat == PreviewEndPlotStatus.Cancel ? false : true;
}
mFun.m_SetSystemVar("BACKGROUNDPLOT", BackGroundPlotVar);
}
else
{
mCommands.m_ed.WriteMessage("\n其他打印正在进行中!");
}
return ret;
}