pdf生成,c++生成pdf文件

  pdf生成,c++生成pdf文件

  PDF是目前流行的电子文档格式,常用于办公自动化(OA)等软件的开发。然而,关于如何制作PDF文件的资料却少之又少,同样的“暴力”破解方式在网上被转贴。代码片段如下:

  StreamWriter pPDF=new StreamWriter(file path);

  ArrayList xRefs=new ArrayList();

  float yPos=0f

  长流开始=0;

  long stream end=0;

  长细流=0;

  string strPDFMessage=null

  //PDF文档标题信息

  strPDFMessage= % PDF-1.1 \ n ;

  converttobyteanddtostream(strPDFMessage);

  外部参照。添加(mPDF。长度);

  strPDFMessage= 1 0 obj \ n

  converttobyteanddtostream(strPDFMessage);

  strPDFMessage=/Length 2 0 R \ n ;

  converttobyteanddtostream(strPDFMessage);

  strPDFMessage= stream \ n

  converttobyteanddtostream(strPDFMessage);

  ……

  看了上面的方法,我打碎了三个杯子。如果我能用上面的原语方法做出一个满意的PDF文件,那一定是天才。后来从一个网站(网址:http://itextsharp . SourceForge . net/index . html)看到了制作PDF文件的控件介绍。我喜出望外,马上下载实验。果不其然,我很轻松的就做出了想要的PDF文件,因为网站是英文的,内容很多,看起来很费力。解决了自己的问题后,看到很多网友还在为PDF文件的制作郁闷,就决定把内容翻译成中文。因为我英语水平一般,很多地方晦涩难懂,所以翻译质量不是很理想。请指正,不过大部分都能看懂。这篇文章的目的一是解决部分网友的燃眉之急,二是抛砖引玉。如果有好朋友愿意准确翻译这个网站的内容,那将是人间一大幸事。

  要用本文的方法生成PDF文件,需要两个控件:itextsharp.dll和ICSharpCode.SharpZipLib.dll。因为样本代码太多,我把所有代码都整理出来放在另一个文件“sample code.doc”里。所有这些资源,我都放在我的ftp站点(ftp://202.107.251.26)的“Pdf文件制作策略”文件夹里(文件夹里另外两个rar压缩文件是两个控件的源代码,供你学习研究)。可以在这里下载相应的资源,也可以直接从原网站下载。

  为了调试和叙述方便,所有例子都是DOS控制台程序,windows程序的使用方法完全一样。按照以下步骤创建可调试项目:

  1.打开VS2003;

  2.点击菜单“文件”“新建”“项目”,在项目类型中选择“Visual C#项目”,在模板中选择“控制台应用程序”,输入“MakePdf”等文件名,指定存储路径,然后点击确定按钮;

  3.在解决方案资源管理器中右击引用,从弹出菜单中选择添加引用,然后在。NET option文件夹添加上面提到的两个应用程序,如下图所示:

  4.在代码窗口的顶部添加两个引用:

  使用iTextSharp.text

  使用iTextSharp.text.pdf;

  至此,准备工作完成。

  第一部分是iText的简单应用。

  第一章创建一个文档。

  用iText: helloword分五步创建PDF文件。

  第一步。创建iTextSharp.text.Document对象的实例:

  Document=new Document();

  步骤2:为该文档创建一个Writer实例:

  PdfWriter.getInstance(文档,新建FileStream(Chap0101.pdf ,FileMode。创建));

  第三步:打开当前文档。

  文档。open();

  步骤4,向当前文档添加内容:

  文档。添加(新段落( Hello World ));

  第五步:关闭文档。

  文档。close();

  完整代码见样本代码0101。

  例中不难看出,做一个PDF文件是非常简单的。

  注意:如果你把“document . add(new paragraph( hello world )”放在例子里;"如果把中的字符串" Hello Word "改成中文,比如"这是我的第一个PDF文件",结果肯定会让你失望,因为生成的PDF文件中没有显示中文。别急,字体问题会在第九章专门讲解,中文显示会解决。如果中文不能正确显示,就没必要翻译这篇文章。

  下面详细介绍步骤。

  第一步是创建文档实例:

  Itsharp.text.document-object有三个构造函数:

  公共文档();

  公共文档(矩形页面大小);

  公共文档(矩形页面大小,

  int marginLeft

  中间边距Right,

  int marginTop,

  int margin bottom);

  第一个构造函数以A4页作为参数调用第二个构造函数,第二个构造函数调用第三个构造函数,每边有36磅的边距。

  u页面大小:

  您可以根据指定的颜色和大小创建自己的页面,示例代码0102创建了一个带有浅黄色背景的细长页面:

  Rectangle pageSize=新矩形(144,720);

  页面大小。BackgroundColor=新颜色(0xFF,0xFF,0x de);

  Document文档=新文档(pageSize);

  通常,您不必创建这样的页面,但是您可以从以下页面大小中进行选择:

  A0-A10,法律,字母,半字母,_ 11x17,分类帐,附注,B0-B5,Arch _ A-Arch _ E,FLSA和FLSE

  在大多数情况下,使用纵向页面。如果要使用横向页面,只需要使用rotate()函数:

  文档文档=新文档(页面大小。a4 . rotate());

  详情见示例代码0103。

  u边距:

  创建文件时,您还可以定义上、下、左、右边距:

  文档文档=新文档(页面大小。A5,36,72,108,180);

  在示例代码0104中,可以看到文档的左边距为0.5英寸,右边距为1英寸,上边距为1.5英寸,下边距为2.5英寸。

  描述:

  创建矩形或设置边距时,您可能需要知道使用什么度量单位:厘米、英寸或像素。实际上,默认的度量系统是根据排版单位磅推导出其他单位的近似值,比如1英寸=72磅。如果您想在A4页面的PDF中创建一个矩形,您需要计算以下数据:

  1厘米/2.54=8.2677英寸

  8.2677英寸* 72=595磅

  27厘米/2.54=11.6929英寸

  1.6929英寸* 72=842磅

  默认边距是36磅或半英寸。

  如果你修改页面大小,它只会影响下一页,如果你修改页边距,它会影响所有,所以要小心。

  对于页面的初始值,请参考步骤3。

  第二步是创建一个编写器实例。

  一旦创建了文档,我们就可以创建文档的Writer的多个实例,它们都继承自抽象类“iTextSharp.text.DocWriter”。

  与此同时,还有另一种情况。可以使用iTextSharp.text.pdf.PdfWriter生成文档pdf文件。如果要创建TeX文档,可以使用iTextSharp.text.TeX.TeXWriter包。

  Writer类的构造函数是私有的,只能通过以下方法创建实例:

  public static xxxWriter getInstance(Document文档,Stream OS);(xxx是Pdf或Xml)

  您可以通过以下方法创建实例:

  pdf writer writer=pdf writer . getinstance(document,new FileStream( chap 01 xx . pdf ));

  但是你几乎不会使用Writer实例(除非你想创建一个高级PDF或者想使用一些非常特殊的功能,比如ViewerPreferences或者Encryption)。所以通过以下方法获取例子就足够了:pdfwriter.getinstance (document,new filestream( chap 01 xx . pdf );

  在第一步创建文档时,第一个参数没有多大意义,第二个参数可以是任何种类的流。到目前为止,我们一直在使用系统。IO.FileStream将文档写入文件,示例代码0105使用System。IO.MemoryStream(这不是一个独立的例子,你要在Servlet引擎中测试这些代码。

  步骤3:打开文档

  u摘要

  在编写任何实际数据之前,您可能希望以下列方式编写一些关于此文档的摘要:

  public boolean addTitle(字符串标题)

  public boolean addSubject(字符串主题)

  public boolean addKeywords(字符串关键字)

  public boolean addAuthor(字符串作者)

  公共布尔addCreator(字符串创建者)

  公共布尔addProducer()

  public boolean addCreationDate()

  public boolean addHeader(字符串名称,字符串内容)

  你可以自己选择标题、主题、关键词、作者、创建程序,但是下面的产品信息会一直添加:iItxSharp(或者iItxSharp的引用)和创建时间(其实这两个方法都是自动调用的)。

  您还可以添加一个自定义名称作为“标题信息”,但这对PdfWriter没有任何作用。如果你查看示例代码0101生成的pdf文件的“文档属性”,我们可以看到只有PDF创建者和产品日期,而示例代码0106的“文档属性”框中有更多的信息。

  打开文档前要做的事情:

  您只能在调用Open方法之前添加摘要,这是iText开发工具提供的一个选项。

  在HTML中,标题信息放在文档前面的标题标识符的中间。调用Open方法将导致头信息被写入流中,因此文档打开后数据无法更改。

  PDF头信息不包括摘要,看起来像这样:

  %PDF-1.2

  这一行显示生成的文档是版本为1.2的PDF文件。在PDF中,摘要保存在PdfInfo对象中,在关闭文档时已经写入PdfWriter。因此,没有任何技术理由不能修改库以满足随时添加或更改摘要的要求。

  u页面初始化

  Open方法将同时在不同的地方生成初始化事件。例如,如果您需要水印或页眉角对象出现在文档第一页的开头,您需要在打开文档之前添加它们。同样用于设置文档其他页面的水印、页眉、角、页码和尺寸。

  当调用以下方法时:

  public bool setPageSize(矩形页面大小)

  公共布尔添加(水印水印)

  public void删除水印()

  设置标题属性

  public void resetHeader()

  设置页脚属性

  public void resetFooter()

  public void resetPageCount()

  设置PageCount属性

  生成的结果只能在下一个新页面中看到(当在这个页面上调用初始化方法时)。代码见示例代码0107。你必须准备一张名为watermark.jpg的图片,如下图所示:

  u阅读器参数:

  您可以通过以下方式为PDF文件指定一些阅读器(如Adobe Reader)参数:

  公共void setViewerPreferences(int首选项)

  在示例代码0108中,指定了以下一些参数:

  writera . setviewerpreferences(pdf writer。pagelayouttwocolumnlight);

  writerb . setviewerpreferences(pdf writer。HideMenubar PdfWriter。hide toolbar);

  writerc . setviewerpreferences(pdf writer。pagelayouttwocolumnlight pdf writer。PageModeFullScreen PdfWriter。NonFullScreenPageModeUseThumbs);

  如您所见,参数可以使用以下一些常量:

  l当文件打开时,页面布局使用下列之一:

  writer . pagelayoutsingpage一次只显示一页。

  pdf writer . pagelayoutonecolumn显示在单列中

  writer . pagelayoutwocolumnlight双栏显示,奇数页在左侧。

  Pdf。pagelayoutwocolumnright-双栏显示,奇数页在右侧。

  l打开文件时,页面模式用于以下情况之一:

  PDF。pagemodeusenone既不显示大钢也不显示缩略图

  pdf writer . pagemodeuseoutlines显示大纲

  pdf writer . pagemodeusethumbs显示缩略图

  Pdf。全屏模式-全屏模式,没有菜单,窗口控件或任何其他窗口可见的控件。

  pdf writer . hide toolbar文档激活时是否隐藏阅读器(如Adobe Reader)的工具栏?

  pdf writer . hidemeubar-文档激活时是否隐藏阅读器的菜单。

  Pdfwriter.hide窗口ui-当文档被激活时,是否隐藏阅读器的界面元素,如滚动条、导航栏等,只保留文档显示?

  pdf writer . fit window是否调整文档窗口的大小以适合第一页的显示。

  pdf writer . center window是否将文档窗口放在屏幕中央?

  l在全屏模式下,指定如何显示界面元素(选择一项)。

  作家。none-既不显示大钢也不显示缩略图。

  作家。nonfullscreenpagemodeuseoutlines显示大钢

  writer . nonfullscreenpagemodeusethumbs显示缩略图

  解释:只能在类PdfWriter中调用这些方法。

  u加密

  在打开文档之前要做的一件事是加密它(如果你希望它被加密的话)。要实现这一目标,您可以使用以下方法:

  public void setEncryption(布尔强度,字符串userPassword,字符串ownerPassword,int permissions);

  强度是以下两个常数之一:

  Pdf.strength40bits位:40位

  Pdf.strength 128bits: 128bits(受Acrobat Reader及以上版本支持)

  UserPassword和ownerPassword可以为空或零长度,在这种情况下,ownerPassword将被随机字符串替换。

  Permissions是下列常量之一:

  PdfWriter。允许打印

  PdfWriter。AllowModifyContents

  PdfWriter。允许复制

  PdfWriter。AllowModifyAnnotations

  PdfWriter。AllowFillIn

  PdfWriter。允许屏幕阅读器

  PdfWriter。AllowAssembly

  PdfWriter。允许降解印刷

  关于此功能,参见示例代码0109和示例代码0110。

  writer.setEncryption(PdfWriter。STRENGTH40BITS,null,null,PdfWriter。allow copy);

  由代码0109生成的文件无需密码即可打开,但用户不能打印或修改该文件。

  writer.setEncryption(PdfWriter。STRENGTH128BITS, userpass , ownerpass ,PdfWriter。AllowCopy PdfWriter。允许打印);

  当您尝试打开示例代码0110生成的文件时,会要求您输入密码( userpass ),因为添加了AllowPrinting参数,您可以毫无问题地打印文档。

  第四步是添加内容。

  在解释第一至第三步的不同例子中,你可能会遇到一些对象,如短语、段落等。在接下来的几章中,所有这些问题都将得到详细的解释。

  有时,您可能希望作者故意忽略由文档生成的行为,例如示例代码0111:

  当我们创建两个writer: writerA和writerB时:

  pdf writer writerA=pdf writer . getinstance(document,new FileStream(Chap0111a.pdf ,FileMode。创建));

  pdf writer writerB=pdf writer . getinstance(document,new FileStream(Chap0111b.pdf ,FileMode。创建));

  我们可以创建两个略有不同的文档:

  莱特拉。pause();

  document.add(新增一段(本段只加Chap0111a.pdf,不加chap 0111 a . pdf ));

  writera . resume();

  你可以比较一下文件:Chap0111a.pdf和Chap0111b.pdf的区别。

  第五步:关闭文档。

  关闭文档非常重要,因为它将关闭正在运行的Writer并将内容写入文件。这个方法在最后被调用,你应该总是关闭文档。

  高级主题:阅读PDF文件

  这部分介绍iText只能生成PDF文件,不能解析PDF文件,所以不会翻译。

  第二章分块、短句和段落

  块

  组块是可以添加到文档中的最小文本单位。组块可以用来构建其他基本元素,如短句、段落、锚点等。Chunk是具有某种字体的字符串。向文档中添加块时,应该定义所有其他布局变量。在下面一行中,我们创建了一个块,内容为“hello World”,红色,斜体,COURIER字体,大小为20:

  Chunk Chunk=new Chunk( Hello world ,font factory . get font(font factory。信使,20,字体。斜体,新颜色(255,0,0)));

  u典型字体1:

  在本指南中,除了第9章(在那里你可以学习使用其他字体),我们将始终使用典型字体1。这些是不同的典型字体1:

  Courier(字体宽度固定)

  Helvetica

  时代罗马

  标志

  ZapfDingbats

  u/删除线

  如果您想要给某些块加下划线或删除线,只需更改字体样式即可:

  Chunk chunk1=new Chunk(此文本带下划线),font factory . get font(font factory。HELVETICA,12,字体。下划线));

  Chunk chunk2=new Chunk(此字体为斜体删除线类型),font factory . get font(font factory。HELVETICA,12,字体。斜体字体。STRIKETHRU))。

  u/下标

  有几个方法可以在一个块中调用,其中大部分将在后面的章节中介绍。本章只介绍一种方法setTextRise(float f)。你可以用这个方法来写上标或者下标的块。

  u盘背景

  如果你想改变块的背景,你可以使用setBackground(Color color)方法。这将在块文本下方添加一个彩色矩形:

  ck.setBackground(新颜色(0xFF,0xFF,0x 00));

  在示例代码0101中,您可以使用setTextRise、setBackground等方法概述典型的字体1和示例。

  条款

  短语是一系列以特定间距(两行之间的距离)为参数的块。一个短句有一个主字体,但是短句中的一些块有不同于主字体的字体。你有更多的选择来创造短句。参见代码0202了解一些特定用途。

  u古希腊语

  因为经常使用古希腊语,所以在Phrase-like的构造函数中有一个特性:取一个字符串作为参数(如果想避免这种情况,只能用块,不能用字符串)。正如您在示例代码0203中所看到的,该特性自动将913到937(除了903)和945到969(古希腊的ASCII值)范围内的所有字体更改为希腊符号。

  不重要

  这与其说是一个功能,不如说是一个缺陷,但无论如何,它使得创建一个非必要的短句或段落成为可能,这将产生一种自下而上书写的临时效果(参见示例代码0204)。如果您想移动页面上的某些位置,这可能会很有用。

  说明过了顶,就查不到了,也没办法让你回到上一页。

  段落

  段落是一系列的块和/或短句。像短句一样,段落也有一定的间距。您也可以指定缩进;在边上和/或右边留一定的空白,段落可以左对齐、右对齐、居中。添加到文档中的每个段落都将自动开始新的一行。创建段落有几种方法,例如:

  段落p1=新段落(新块(这是我的第一段。,font factory . get font(font factory。HELVETICA,12)));

  段落p2=新段落(新短语(这是我的第二段。,font factory . get font(font factory。HELVETICA,12)));

  段落p3=新段落(这是我的第三段。,font factory . get font(font factory。HELVETICA,12));

  一些对象将被添加到段落中:

  p1.add(可以添加字符串,);p1.add(new Chunk(可以添加Chunk ));p1.add(新短语(或者您可以添加短语。));

  解释:一个段落有且只有一个空格。如果添加不同字体的短句或块,原始间距仍然有效。您可以通过设置SetLeading来更改间距,但是段落中的所有内容都将使用新的间距。参见示例代码0205。

  保持段落的完整性。

  在示例代码0206中,我们使用setKeepTogether(true)方法尝试将一个段落放在同一页面上。这种方法并不总是有效。比如第一段放不下一页,就分成两部分。第二段放在第二页,但第三段在第三页之后。

  字体的延续

  你应该掌握一些字体延续的规则。关于这些规则的应用,参见示例代码0207。当我们用指定的字体(不是默认字体)创建一个短句或段落,然后添加更多内容时,初始对象的字体样式将被延续。请看“Hello 1!”和“你好2”:

  短语myPhrase=新短语( Hello 2!,新字体(字体。TIMES_NEW_ROMAN,8,字体。粗体));

  我的短语。添加(新短语(一些其他字体),新字体(字体。HELVETICA字体,8。斜体)));

  我的短语。添加(新短语(这是句子的结尾。\n ,新字体(字体。TIMES_NEW_ROMAN,8,字体。斜体)));

  文档。添加(my phrase);

  我们从Times New Roman bold开始,使用Helvetica字体添加了一些文本,但没有指定样式。我们发现文本被改为粗体。当我们使用Times New Roman字体和斜体添加更多文本时,结果变成了粗斜体。

  如果我们使用FontFactory创建字体,该字体样式将不会被延续,因为FontFactory使用另一种技术来构建字体:

  myPhrase=新短语( Hello 1bis!,font factory . get font(font factory。TIMES_NEW_ROMAN,8,字体。粗体));

  我的短语。Add(新短语(某个其他字体),font factory . get font(font factory。HELVETICA字体,8。斜体)));

  我的短语。添加(新短语(这是句子的结尾。\n ,font factory . get font(font factory。TIMES_NEW_ROMAN,8,字体。斜体)));

  文档。添加(my phrase);

  在上面的代码中,没有指定使用Helvetica字体的文本样式字体(既不是粗体也不是斜体)。Times New Roman中的额外文本仅以斜体显示。

  你可以看到,我们增加了一个段落,就像一个短句。

  段落myParagraph=新段落( Hello 1!,新字体(字体。TIMES_NEW_ROMAN,8,字体。粗体));

  我的段落。添加(新段落(这是句子的结尾。,FontFactory.getFont(新字体。TIMES_NEW_ROMAN,8)));

  文档。添加(我的段落);

  可以不这么做,但是会失去字体风格的延续。首先,创建一个没有任何字体的段落(在这个例子中,我们只将字体间隔1.5倍),然后添加内容的不同部分。

  myParagraph=新段落(12);

  我的段落。添加(新段落( Hello 3!,新字体(字体。TIMES_NEW_ROMAN,8,字体。粗体)));

  我的段落。添加(新段落(这是句子的结尾。,新字体(字体。TIMES_NEW_ROMAN,8,字体。斜体)));

  文档。添加(我的段落);

  如果您使用短语对象,您也将失去字体样式的连续性:

  myPhrase=新短语(12);

  我的短语。添加(新短语( Hello 4!,新字体(字体。TIMES_NEW_ROMAN,8,字体。粗体)));

  我的短语。添加(新短语(这是句子的结尾。,newFont(字体。TIMES_NEW_ROMAN,8,字体。斜体)));

  文档。添加(my phrase);

  u更改分隔符

  通常,当文本不能放在一行中时,文本将被分成不同的部分。iText将首先寻找分割器,如果没有找到,文本将在行尾被截断。有一些预先确定的分隔符,如" "空格和"-"连字符,但您可以使用setSplitCharacter方法来覆盖这些默认值。在示例代码0208中,您可以看到当到达行尾时,块是如何划分的。然后,分隔符变为点“.”线被分开的地方。

  第三章定位点、列表和注释

  定位点

  我们都知道HTML中的超文本链接。当我们点击某些报表时,您可以跳转到互联网上的其他页面。这个功能也可以用PDF实现。其实第11章整章都有PDF链接的介绍,不过这是iText更高级的应用。在这一章中,我们处理简单的iText。

  如果您想给一个文档添加外部链接(例如,使用URL链接到WEB上的其他文档),您可以简单地使用Anchor对象,它是从Phrase对象派生出来的,并且以相同的方式使用。只有两个额外的方法来定义两个额外的变量:setName和setReference。

  外部链接示例:

  Anchor anchor=新锚点(网站,font factory . get font(font factory。HELVETICA,12,字体。下划线,新颜色(0,0,255)));

  锚。reference= http://itextsharp . SourceForge . net ;

  锚。Name= website

  如果你想添加一个内部链接,你需要为链接选择一个不同的名字,就像你在HTML中使用名字作为锚点一样。要实现这一点,需要加一个“#”。

  内部链接示例:

  Anchor anchor1=新锚点(这是内部链接);

  主播1。Name= link1

  Anchor anchor2=新锚点(点击此处跳转到内部链接);

  锚。Reference= # link1

  有关这两个链接的示例,请参见示例代码0301。

  以表格或栏的形式排列

  Classes List和ListItem允许您向PDF文件添加列表,并且您还可以选择是否对列表进行排序。

  排序列表示例:

  List list=新列表(true,20);

  列表。Add(新的ListItem(第一行));

  列表。Add(new ListItem(第二行更长,看看到达行尾后会发生什么。它会从新开始吗?));

  列表。Add(新ListItem(第三行));

  结果如下:

  首行

  第二行更长,看看到达行尾时会发生什么。它会从新开始吗?

  第三线

  不排序的示例如下:

  List overview=new List(false,10);

  概述。Add(新的ListItem(这是一个项目));

  概述。Add(这是另一个项目);

  结果如下:

  这是一个项目

  这是另一个项目

  您可以通过setListSymbol方法更改列表符号:

  //使用字符串作为列表符号

  列表1。ListSymbol= *

  //使用Chunk作为列表符号(包括“# 8226;”字符)

  列表2。ListSymbol=new Chunk(\u2022 ,font factory . get font(font factory。HELVETICA,20));

  //使用图片作为列表符号

  清单3。list symbol=new Chunk(image . getinstance( my bullet . gif ),0,0);

  还可以使用setIndentationLeft和setIndentationRight方法来设置缩进。列表符号的缩进是在构造函数中设置的。更多示例见示例代码0302。

  给…作注解

  IText支持不同风格的注释。

  u文本注释:

  您可以在文稿中添加一小段文本,但它不是文稿内容的一部分。注释有标题和内容:

  注释a=新注释(

  作者,

  “也许是因为我想成为一名作家,所以我写了它,”);

  u外部链接注释:

  您需要指定一个可点击的矩形和一个字符串(URL描述)或URL对象:

  Annotation annot=new Annotation(100 f,700f,200f,800f,new URL( http://www . lowa gie . com );

  Annotation annot=new Annotation(100 f,700f,200f,800f, http://www . lowa gie . com );

  u外部PDF文件链接注意:

  您需要指定一个可点击的矩形和一个字符串(文件名)以及目标文件或页码。

  Annotation annot=new Annotation(100 f,700f,200f,800f, other.pdf , mark );

  Annotation annot=new Annotation(100 f,700f,200f,800f, other.pdf ,2);

  u指定行为链接注释。

  您需要指定一个可点击的矩形和一个指定的行为:

  Annotation annot=new Annotation(100 f,700f,200f,800f,p division。首页);

  u应用程序链接注释:

  您需要指定一个可点击的矩形和一个应用程序:

  Annotation annot=new Annotation(300 f,700f,400f,800f, C://winnt/notepad.exe ,null,null,null);

  我们不需要在页面上指定位置。iText会在内部处理。可以看到iText在页面当前位置下方添加了文本注释,第一个在段落后第一行下方,第二个在短句结尾下方。

  所有其他注释都需要指定要匹配的矩形区域。在示例代码0304中,我们画了一些方块(使用的函数将在第10章介绍),并为每个方块添加了一些链接注释。

  第四章页眉、页脚、章节、区域和绘图对象

  使用第3章到第5章中描述的大量简单iText对象可以避免更高级的主题(第9章到第12章)。记住这些简单对象限制的函数,大量复杂函数在第3部分。

  页眉页脚

  HeaderFooter对象可用于为文档的每一页添加页眉和页脚。这种页眉或页脚包含一个标准短句(如果需要)和当前页码。如果你需要更复杂的页眉和页脚(使用表格或者哪一页有几页),请阅读第12章。

  在示例代码0401中,您可以看到我们首先添加了一个页脚,其中包含没有任何边框的页码。

  header footer footer=new header footer(新短语(这是页面: ),true);

  页脚。边框=矩形。NO _ BORDER

  文档。页脚=页脚

  我们也可以使用下面的构造函数:

  header footer footer=new header footer(新短语(这是页面),新短语(.));

  构造函数知道你想添加一个页码,并把它放在两个短句之间。如果你只是设置了一个HeaderFooter而没有改变边框,那么在页眉或页脚文本的上下会有一条直线。

  header footer header=new header footer(新短语(这是没有页码的页眉),false);

  文档。Header=表头;

  部分和区域

  第11章将描述如何建立一棵树的外观。如果你只需要一个简单的章节和(子)区域,你可以用章节对象和小节对象自动构建一个树:

  Paragraph cTitle=new Paragraph(这是第1章,chapter font);

  Chapter章=新章节(cTitle,1);

  Paragraph sTitle=new Paragraph(这是第一章的第一节,section font);

  section section=chapter . add section(sTitle,1);

  在示例代码0402中,我们添加了一系列章节和子区域,您可以看到完整的树形结构,并且树形结构是默认打开的。如果希望关闭某些节点,必须使用BookmarkOpen属性,该属性的值为false。详情见样本代码0403。

  图表

  如果要添加图形,比如线、圆、几何形状等,要看十章,但如果只需要一些有限的功能,可以使用图形对象。

  Graphic grx=新图形();

  //添加一个矩形

  grx.rectangle(100,700,100,100);

  //添加斜线

  grx.moveTo(100,700);

  grx.lineTo(200,800);

  //显示图形。

  grx . stroke();

  文档。添加(grx);

  完整代码见样本代码0404。如果你想看到所有的方法,请查看PdfContentByte对象API。

  当您想要为页面添加边框或在文本的当前位置绘制水平线时,图形对象非常有用。下面的方法使用指定的宽度、间距(如果需要)和颜色绘制边框。

  public void setBorder(浮动线宽,浮动额外空间);

  public void setBorder(浮动线宽、浮动额外空间、颜色颜色);

  下面的方法用指定的宽度(如果需要)和颜色绘制一条水平线。线条的长度是指定边缘之间可用区域的百分比。

  公共void setHorizontalLine(浮动线宽,浮动百分比)

  公共void setHorizontalLine(浮动线宽、浮动百分比、颜色)

  例5中有一个边框,线宽3磅,距离边框5磅,有两条水平线,一条是黑色,5磅宽,100%可用空间,另一条是红色,线宽3磅,80%可用空间。

  第五章形式

  重要提示:如果只生成PDF文件(没有XML、HTML、RTF……),最好使用class pdfPTable而不是class Table。

  一些简单的表格。

  表格是包含排列成矩阵的单元格的矩形区域。表格的矩阵不必是mn,它可以有比单个矩阵大的孔或单元。

  创建表格最常用的方法是预先知道有多少行和多少列:

  公共表(int列,int行);

  在示例代码0501中,我们构建了一个简单的表:

  Table Table=new Table(2,2);

  table . addcell( 0.0 );

  table . addcell( 0.1 );

  table . addcell( 1.0 );

  table . addcell( 1.1 );

  这个表格有两行和两列。单元格会自动添加,从第一行和第一列开始,然后是第二列。当一行已满时,下一个单元格会自动添加到下一行的第一列。

  您还可以将单元格添加到表格中的指定位置,如示例代码0502所示。我们没有添加System.Drawing.dll引用来获取点对象,而是创建了一个4行4列的表格,然后在随机位置添加了一些单元格:

  Table Table=new Table(4,4);

  可食用的。AutoFillEmptyCells=true

  Table.addCell(2.2 ,new Point(2,2));

  aTable.addCell(3.3 ,新点(3,3));

  Table.addCell(2.1 ,new Point(2,1));

  aTable.addCell(1.3 ,新点(1,3));

  您可以看到我们将AutoFillEmptyCells属性设置为true,这将自动用默认的单元格布局填充空单元格。如果我们忘记这样做(就像这个例子中的第二个表),就不会添加额外的单元格,并且不包含任何单个单元格的行也将被忽略。在本例中,第一行将不显示,因为它是一个空行。

  经常使用数据库查询结果来填充表格。在大多数情况下,您并不知道需要多少行,这就是为什么有第二个构造函数:

  公共表(int列);

  IText会根据需要自动添加行。在示例代码0503中,初始化了4行和4列。当我们在第6行和第7行添加单元格时,iText会自动将行数增加到7。

  也可以增加列数,但是有点麻烦。不能自动生成。您必须使用addColumns方法并设置列宽。详情见样本代码0504。

  一些表格参数

  上例中的表格不美观。我们可以设置很多参数来改变表格的外观。类表和类单元格是从类Rectangle派生的。我们可以使用很多典型的矩形方法。让我们来看看示例代码0505。

  Table table=新表(3);

  桌子。border width=1;

  桌子。BorderColor=新颜色(0,0,255);

  桌子。单元格填充=5;

  5.桌子。单元格间距=5;

  Cell cell=新单元格(表头);

  细胞。Header=true

  细胞。colspan=3;

  table.addCell(单元格);

  10.cell=新单元格(“具有列跨度1和行跨度2的示例单元格”);

  细胞。rowspan=2;

  细胞。BorderColor=新颜色(255,0,0);

  table.addCell(单元格);

  table . addcell( 1.1 );

  15.table . addcell( 2.1 );

  table . addcell( 1.2 );

  table . addcell( 2.2 );

  table . addcell(“cell test1”);

  cell=新单元(大单元);

  20.细胞。rowspan=2;

  细胞。colspan=2;

  细胞。BackgroundColor=新颜色(0xC0,0xC0,0xc 0);

  table.addCell(单元格);

  table . addcell( cell test2 );

  25.文档。添加(表格);

  u单元格间距和填充

  在第四行中,我们设置了表格的填充,即在单元格边界和内容之间留出一定的空间。在前面的例子中,我们看到文本靠近边界,这可以通过使用特定的填充来避免。

  在第五行中,我们设置了表格的间距,即单元格与表格边界之间有一定的空间,不同单元格之间使用一半的空间。具体代码见示例代码0506。

  u对齐

  在示例代码0506中,我们还更改了单元格“大单元格”的对齐方式:

  细胞。HorizontalAlignment=Element。ALIGN _ CENTER

  细胞。VerticalAlignment=元素。ALIGN _ MIDDLE

  注意:你不能总是相信垂直对齐。

  u形边框

  如果我们像第14行那样添加一个单元格,我们将使用默认的单元格布局(默认布局可以通过SetDefalut方法更改)。如果我们使用单元格对象,我们可以控制每个单元格的布局。

  在第二个和第三个步骤中,我们设置了整个表格的边框宽度和颜色,这些方法我们可以用在单元格上。在12行中,每个单元格都以“框”作为边界绘制(如在HTML中),但示例代码0507表明我们在PDF中有更多的可能性。

  u颜色

  在第22行,您还可以定义单元格的背景颜色。在示例代码0507中,我们不使用颜色,而是用一定的灰度填充。

  u跨度和柱跨度

  最后,您还可以设置单元格的行跨度(11/20行)和列跨度(8/21列)。这样,几个单元格可以合并成一个大的单元格。

  u 备注

  第7行在PDF中没有意义,用于生成HTML,在HTML中并不是总能产生同样的布局,PDF表格有点象:

  header

  example cell with colspan 1 and rowspan 2

  1.1

  2.1

  1.2

  2.2

  cell test1

  big cell

  cell test2

  u 表格分割

  如果一个表格不能放在一页中,将自动被分割,示例代码0508显示了当一个表格到达页边时发生的情况,这将在下一节中解释。

  大表格

  跨越几页的表格将自动被分割成不同的部分。示例代码0509显示了一个跨越多页的报表。该报表有一个表头,如果你希望这个表头在每页都出现,你可以用endHeaders()方法标记表头区域的结束点,见示例代码0510。

  为做这样的报表,建议设置单元格间距为0和仅使用指定的填距。

  你可能已经注意到了,当一个表格被分割时,一些边界好象丢失了。这是因为单元格在前一页被完整地绘制了而不会传递给下一页。

  u 强行将一个表格或单元格布置到一页上

  有有些情况下,你可能希望避免单元格或者整个表被拆分成两个部分,示例代码0511差不多和示例代码0508完全一样,但我们设置了参数TableHasToFit为true,看看示例代码0508和示例代码0511结果区别。在示例代码0512中我们修改了示例代码0510的CellsHaveToFit属性为true,比较两个示例产生结果的区别。

  内存管理

  当我们添加一个对象到文档时,该对象一有可能就写入了输出流,但当创建一个表格时,该Table对象一直保存着,对于真正的大表格,这将成为一个问题。

  同样,当你正写一个HttpServletResponse对象到输出流时,浏览器也可能超时。这就是为什么你自己用fitsPage()方法控制表分割是有用的,示例代码0513告诉你如何做。

  嵌套表格

  有两种方法嵌套表格,第一种是利用insertTable方法明确地将一个表格插入到另外一个表格,示例代码0514显示了通过插入到其他表格的办法创建的5个表格。正如你看到的在前面两个表中,所有空的单元格自动得到分割,因为改变了原来的表格。如果一个单元格不空,列跨度和(或)行跨度将自动调整到新的位置,页面上第三个表格显示所有原表中列的相关宽度都得到了保护,第四个表格显示我们可以在插入了表格后添加其他单元格:该单元格自由地添加到下一个单元格中。最后是一个深度嵌套的表格。

  当你使用insertTable方法时,插入表的宽度百分比不会被考虑,如果你希望插入表仅占单元格的80%(这是默认的宽度百分比),你不得不在单元格中绕排,见示例代码0515,这也是让一个表结合其他数据存放在同一个单元格中的唯一办法,见示例代码0516。

  备注:你只能将一个表格插入到列跨度和行跨度均为1的单元格中。

  表格偏移

  当一个表格被添加到文档之前,以当前间距为准的新行将被添加(如前一个插入对象的间距)。有时因为前一个插入对象和当前表格间的间距过大或过小你并不希望这样做,如果你想改变这个空间,你不得不设置表格偏移,如示例代码0517。

  表格的绝对位置

  iTextSharp.text.Table是一个通过标准方法创建表格的相当简单的类,但有时你希望表格有一些特殊的行为,这种情况下你将使用更复杂的类com.lowagie.text.pdf.PdfPTable,示例代码0518是一个非常简单的例子,在第十章和十二章中将有一些更复杂的例子。

  第六章 图片

  Image对象

  如果你学习过API,你可能已经注意到可以通过几种构造函数来创建图片,本手册中,我们将仅仅告诉你最简单的解决方案,如访问通过文件名或URL确定的图片生成的Image对象。

  public static Image getInstance(Uri url)

  public static Image getInstance(string filename)

  Image是一个抽象类,故得到实例的方法将判断给出的图片的类别(GIF、Jpeg、PNG……)并返回对象的类别Gif、Jpeg、Png……,一些图片会被忽略,如果你想知道哪些图片会被忽略,请查阅FAQ(http://www.lowagie.com/iText/faq.html#images)。

  u 通过URL得到图片实例

  这是添加一个图片最简单的办法,见示例代码0601,我们添加了一个WMF、一个Gif、一个Jpeg和一个PNG图片到文档中,使用4个URL得到:

  Image wmf = Image.getInstance(new URL("../examples/harbour.wmf"));

  Image gif = Image.getInstance(new URL("../examples/vonnegut.gif"));

  Image jpeg = Image.getInstance(new URL("../examples/myKids.jpg"));

  Image png = Image.getInstance(new URL("../examples/hitchcock.png"));

  备注:许多PDF库在插入一个图片前都将其解压缩并转换成位图格式,下面是几个我为什么不这样做的原因:

  这将导致PDF文件增大,这样产生的PDF文件尺寸是不同图片文件尺寸总和的数十倍。

  面临一个法律问题:LZW算法受专利保护,所以不允许使用这种算法来解压缩GIF等文件。

  u 通过文件名得到图片实例

  通过简单地改变图片引用路径将示例代码0601改成示例代码0602:

  Image gif = Image.getInstance("vonnegut.gif");

  Image jpeg = Image.getInstance("myKids.jpg");

  Image png = Image.getInstance("hitchcock.png");

  同示例代码0601的区别只是该图象从本地获取而已,另外一个例子见示例代码0603。

  图片的位置

  u 对齐方式

  通过下面方法设置图片的对齐方式:

  Alignment = Image.RIGHT

  Alignment = Image.MIDDLE

  Alignment = Image.LEFT

  参见示例代码0604。

  我们将Vonnegut的图片放在右边,小孩的图片放在中间,hitchcock的图片放在左边。

  u 图片和文本

  另外,你还可以指定文本相对图片的环绕方式:

  Alignment = Image.RIGHT Image.TEXTWRAP

  Alignment = Image.MIDDLE

  Alignment = Image.LEFT Image.UNDERLYING

  见示例代码0506,文字在Vonnegut图片的左侧,并不在我小孩的图处环绕,且排在Hitchcock图片的上面。

  说明:该功能尚有一些BUG。

  u 绝对位置

  当制作PDF文件时,你可能用到该方法:

  public void setAbsolutePosition(int absoluteX, int absoluteY)

  将一个图片放要页面上一个绝对位置的代码见示例代码0606,我们在不同的坐标处添加了两幅图片,这里使用给定的坐标将图片放在了左下角,通过将图片的宽度和高度作为X和Y坐标将设置第一个图片,坐标的2倍设置第二个图片。

  缩放和旋转图片

  u 缩放

  有几种办法可以缩放图片:

  public void scaleAbsolute(int newWidth, int newHeight)

  public void scalePercent(int percent)

  public void scalePercent(int percentX, int percentY)

  public void scaleToFit(int fitWidth, int fitHeight)

  小孩的图片大小为194×202象素,如果你想让图片小一些,你可以通过scaleAbsolute(97, 101)进行缩放,使用scalePercent(50)也能到达同样的效果。

  还可以通过scaleAbsolute(194, 101)来减小,所以这些例子都放在了示例代码0607中。

  u 对分辨率的影响

  如果一个图片不经任何缩放,其分辨率(resolution)为72,如果该图片缩放比例为50%,则分辨率为144,如果有更低的缩放比,则分辨率将更大,因为象素相同但尺寸变得更小了。使用72/300=24%的比例放置一个300dpi的图片,例:你用300dpi扫描了一个5×5英寸的图片,图片结果为1500×1500象素(5×300),当你用24%(72/300=0.24)的比例将该图片放置到PDF文件中时,PDF中的图片将为5×5英寸1500X1500象素300dpi,该图片将始终为1500X1500象素而不管尺寸如何。

  u 旋转

  可以通过下面的方法旋转图片

  public void setRotation(double r)

  详见示例代码0608。

  原始图片数据

  到目前为止,所有例子中使用的图片均来自地本地磁盘或者某个网站,但也可能使用包含图片信息的数组来得到图片的实例:

  public static Image getInstance(byte[] img)

  该方法同前面方法的效果相同,返回一个新的Gif,Jpeg或者Png类别的Image对象。

  在示例代码0609中,我们添加一个从一个Jpeg文件中读入到字节数组中的图片,很明显,使用其他getInstance方法得到实例更优越,但这仅仅是一个例子,该getInstance方法在动态创建那些根本不存在的图片时非常有用。

  该例子也演示了如何创建和使用一个原始图片。

  public static Image getInstance(int width, int height, int components, int bpc, byte data[])

  本例中创建了一个100×100象素的图片,因为每个象素用RGB描述,所以图片大小为100×100×3字节。

  System.Drawing.Bitmap

  示例代码0610是一个比较高级的话题,理由如下:

  首次使用到了System.Drawing.Bitmap类。该类在.net框架中,可以使用更多类型的图片,如TIFF、GIF,而这些图片在iText中均不支持,你可以检查一下.net框架看看你需要的图片格式是否得到支持。

  前面的例子中,还有一些事情要注意:当添加一个图片时不会出现什么问题,文字始终浮于图片上面,本例中,我们希望图片浮在文字上面。这也是为什么我们将使用iTextSharp.text.pdf.PdfContentByte类的原因(见第十章)。

  你将发现使用的图片为透明的gif格式,你可以到http://itextsharp.sourceforge.net/examples/h.gif下载得到。

  TIFF和CCITT

  示例代码0611也是一个比较高级的话题,例中转换一个TIFF文件到PDF文件。

  u 图片遮罩

  示例代码0613在,我们创建了一个用作遮罩的图片

  3C

  7E

  E7

  C3

  C3

  E7

  7E

  3C

  该图片尺寸为8×8象素,每组一个字节,使用makeMask()方法可以转换成遮罩。

  byte maskr[] = {(byte)0x3c, (byte)0x7e, (byte)0xe7, (byte)0xc3, (byte)0xc3, (byte)0xe7, (byte)0x7e, (byte)0x3c};

  Image mask = Image.getInstance(8, 8, 1, 1, maskr);

  mask.makeMask();

  mask.setInvertMask(true);

  我们可以用该遮罩直接遮住其他图片的一部分。

  PdfContentByte cb = writer.DirectContent;

  Image image = Image.getInstance("vonnegut.gif");

  image.ImageMask = mask;

  或者我们将该遮罩用于模板遮罪中。

  PdfContentByte cb = writer.DirectContent;

  cb.setRGBColorFill(255, 0, 0);

  cb.addImage(mask, mask.scaledWidth() * 8, 0, 0, mask.scaledHeight() * 8, 100, 400);

  关于ContentByte对象更多信息请参见第十章。

  图片和其他对象

  u 图片在块中

  有时,可以方便地将图片置于块中,通过一定偏移将一个图片置于块中:

  Chunk ck = new Chunk(img, 0, -5);

  具体代码见示例代码0614,我们可以添加该特殊图片块到短句、表格等,本例中的图片请到http://itextsharp.sourceforge.net/examples/pngnow.png下载。

  u 图片在表格中

  你可以将图片添加到单元格中,但有两个副作用:

  l 表格的宽度是确定,当图片超出单元格的宽度时,将自动缩小。

  l 你不能进行文字绕排和为图片添加下划线。

  参见示例代码0615。

  u 图片链接注释

  如果你希望得到一个可点击的图片,或者想添加链接注释到图片上,你需要创建一个Annotation对象,并添加到图片上,你不需要指定位置(你可以使用0,0,0,0),该位置会内部更新以适合该图片。

  gif.Annotation = new Annotation(0, 0, 0, 0, "Chap1102b.pdf", 3);

  jpeg.Annotation = new Annotation("picture", "These are my children", 0, 0, 0, 0);

  参加示例代码0616。

  第二部分 其他文档格式

  第七章 XML和 (X)HTML

  本章主要介绍了如何利用iText控件生成XLM文档和(X)HTML文档,但我们对这些并不感兴趣,故只介绍本章中提到的将XML转为PDF。

  在第一章中,我们通过5步生产一个PDF文件,为了将一个XML文件转换为PDF文件,只需重写第3和第4步,第5步由解析器自动处理。

  //第3步:创建一个解析器并设置文档句柄:

  iTextHandler h = new iTextHandler(document);

  //第4步,转换该文档:

  h.Parse("Chap0701.xml");

  示例代码见示例代码0702

  第八章 RTF文件

  RTF包

  RTF包是基于iText包扩展出来的,允许iText除生成PDF文件外还可以输出RTF文件,除了一些在RTF包中不支持的特性外,大多数PDF文件特性都可以使用。

  创建一个RTF文档

  创建一个RTF文档和创建一个PDF文档方法是一样的,都是这基本的5步,唯一的区别是第2步中用RtfWriter代替了PdfWriter,见示例代码0801。

  第1步 创建一个the iTextSharp.text.Document对象的实例:

  Document document = new Document();

  第2步 创建一个document的RtfWriter将document写入你选择的输出流:

  RtfWriter.getInstance(document, new FileStream("Chap0801.rtf"), FileMode.Create);

  第3步 打开document:

  document.Open();

  第4步 添加内容到document

  document.Add(new Paragraph("Hello World"));

  第5步 关闭document

  document.Close();

  关于如何创建其他对象并添加到document中,请参见其他章节的内容。

  不支持的特性

  水印

  阅读器参数

  加密

  内嵌字体

  块间距

  段落右缩排

  列表右缩排

  无圆点符号列表

  嵌套表格

  除JPEG和PNG的其他图片

  RTF中扩展的页眉和页脚

  写入RTF时无法在开始新页前通过setHeader方法改变文档的页眉或页脚,这里有两个办法来解决这个问题。

  利用“Chapters”,添加一个新“chapter”到文档前,使用setHeader或setFooter,你可以在不同的“Chapters”中使用不同的页眉或页脚,见示例代码0802。

  使用RtfHeaderFooters类。该类允许你设置4个页眉或页脚,并指定在哪页出现。你当然可以结合Chapter创建4个不同的页眉或页脚,见示例代码0803。

  u 使用RtfHeaderFooters类

  第1步创建一个RtfHeaderFooters类:

  RtfHeaderFooters headers = new RtfHeaderFooters();

  第2步添加HeaderFooter对象

  headers.Add(RtfHeaderFooters.LEFT_PAGES, new HeaderFooter(new Phrase("This header is only on left hand pages")));

  headers.Add(RtfHeaderFooters.RIGHT_PAGES, new HeaderFooter(new Phrase("This header is only on right hand pages")));

  第3步如同使用页眉页脚一样使用RtfHeaderFooters

  document.Header = headers;

  使用RtfHeaderFooters.add(...)的常量:

  FIRST_PAGE: 在你文档的第一页使用该页眉或页脚。你将使用rtfWriter.HasTitlePage = true来完成

  LEFT_PAGES: 所有左边页均使用该页眉或页脚

  RIGHT_PAGES: 所有右边页均使用该页眉或页脚

  ALL_PAGES: 所有页均使用该页眉或页脚,只有和FIRST_PAGE 结合使用才有意义。

  有一件事非常重要:如果你使用LEFT_PAGES或者RIGHT_PAGES来设置页眉或页脚,再使用ALL_PAGES,页眉和页脚均不会起作用。

  表格效果见示例代码0804。

  第三部分 iText的高级应用

  第九章 字体

  本章原文讲了许多字体的使用技巧,但就是没有讲如何使用中文,因此,意义不大,再说,如果不支持中文,前面的也就白翻译了,因此,根据原文讲到的一些知识,我摸索出汉字的使用方法,自己写了本章内容,应该算是“原创”了吧^_^(哎呀!谁拿鸡蛋扔我……)。

  Windows中一般都是使用TrueType字体,每个中文版Windows操作系统均默认安装了宋体、仿宋、黑体和楷体四种字体,你还可以安装其他第三方字体,如安装了Office 2000后,会自动安装华文行楷等字体,比较奇怪的是,在PDF文件中插入了一种本计算机才有的字体,在打开PDF文件的计算机上虽然没有该字体,但仍然能正常显示!这有别于Word文件,Word文件将当前计算机中没有的字体一律用宋体代替,这大概是意外收获吧。

  字体文件一般保存在windir\Fonts目录中,扩展名为TTF,还有扩展名为TTC的字体文件,也是TrueType字体,不过是一个集。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • php读取pdf数据,php pdf读取
  • php读取pdf数据,php pdf读取,PHP中使用mpdf 导出PDF文件的实现方法
  • kotlon协程,深入理解kotlin协程pdf,一文彻底搞懂Kotlin中的协程
  • 深入解析C#(第4版),深入解析css pdf,深入解析contentWindow, contentDocument
  • java 反射机制原理与用法详解视频,java 反射机制原理与用法详解pdf
  • java 反射机制原理与用法详解视频,java 反射机制原理与用法详解pdf,Java 反射机制原理与用法详解
  • ,,Java使用iTextPDF生成PDF文件的实现方法
  • ,,Python利用PyMuPDF实现PDF文件处理
  • 漫画算法小灰的算法之旅pdf,漫画算法2-小灰的算法进阶
  • devops和自动化运维实践 PDF,devops思想在运维方面的具体实践
  • pdf如何去除水印,pdf去水印的三种方法
  • 把a4的内容打印成a3小册子,a4的pdf文档如何打印成a3
  • nlp自然语言处理入门pdf,精通python自然语言处理 pdf
  • 容器docker基本操作,每天5分钟玩转docker容器技术 pdf
  • sklearn中文手册pdf下载,sklearn库模块及函数
  • 留言与评论(共有 条评论)
       
    验证码: