一、前言

首先需要在Maven中添加相应的jar包依赖,若项目没用到Maven,也可自行下载相应所需的jar包(itextpdf.jar 与 itext-asian.jar),如下图所示。点此下载

Maven中添加依赖jar包如下所示:

 <!-- pdf start -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.3.2</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<!-- pdf end -->

二、正文

1、首先获取需要填写至PDF中的数据,如下述所示,realPath为添加图片的路径,test.pdf为未添加图片的PDF临时文件,在Tomcat服务器对应路径下,以及导出的PDF文件存至桌面:

 //点击下载获取企业信息并存至Pdf
@RequestMapping(value="/downloadPdf.do")
@ResponseBody
public String downloadPdf(@RequestParam(value = "download_corp_id") String download_corp_id, HttpServletRequest request) throws Exception {
List<TCorp> corpIfs = searchCorpService.getCorpInfo(Integer.parseInt(download_corp_id));
TCorp tCorp = new TCorp();
for (TCorp corpInfo: corpIfs){
tCorp.setId(corpInfo.getId());
tCorp.setRegNo(corpInfo.getRegNo());
tCorp.setCorpName(corpInfo.getCorpName());
tCorp.setCorpAddr(corpInfo.getCorpAddr());
tCorp.setBelongOrg(corpInfo.getBelongOrg());
tCorp.setBelongDistOrg(corpInfo.getBelongDistOrg());
tCorp.setBelongTrade(corpInfo.getBelongTrade());
tCorp.setEconKind(corpInfo.getEconKind());
tCorp.setAdmitMain(corpInfo.getAdmitMain());
tCorp.setStartDate(corpInfo.getStartDate());
tCorp.setCheckDate(corpInfo.getCheckDate());
tCorp.setOperManIdentNo(corpInfo.getOperManIdentNo());
tCorp.setOperManName(corpInfo.getOperManName());
tCorp.setCorpStatus(corpInfo.getCorpStatus());
tCorp.setRegCapi(corpInfo.getRegCapi());
tCorp.setPaidCapi(corpInfo.getPaidCapi());
tCorp.setFareTermStart(corpInfo.getFareTermStart());
tCorp.setFareTermEnd(corpInfo.getFareTermEnd());
tCorp.setFareScope(corpInfo.getFareScope());
tCorp.setUniScid(corpInfo.getUniScid());
tCorp.setCorpTel(corpInfo.getCorpTel());
tCorp.setCorpWebUrl(corpInfo.getCorpWebUrl());
tCorp.setCorpLogo(corpInfo.getCorpLogo());
tCorp.setCorpEmail(corpInfo.getCorpEmail());
tCorp.setPracPersonNum(corpInfo.getPracPersonNum());
tCorp.setOrgInstCode(corpInfo.getOrgInstCode());
tCorp.setTaxpayNum(corpInfo.getTaxpayNum());
tCorp.setStaffSize(corpInfo.getStaffSize());
tCorp.setEnglishName(corpInfo.getEnglishName());
tCorp.setFormerName(corpInfo.getFormerName());
tCorp.setCorpInfo(corpInfo.getCorpInfo());
tCorp.setCreateDate(corpInfo.getCreateDate());
tCorp.setCreateOrg(corpInfo.getCreateOrg());
} String realPath = request.getSession().getServletContext().getRealPath("/") + "\\icon\\logo_64.png";
PDFReport.settCorp(tCorp);
new PDFReport("test.pdf").generatePDF();
PDFUtil.addImage("test.pdf", "C:\\Users\\Administrator\\Desktop\\"+tCorp.getCorpName()+".pdf",realPath); return "提示:数据导出成功!";
}

2、PDFReport类中申明一个文档类型建立Document对象,设置页面样式等:

 package util;

 import com.itextpdf.text.Document;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import entity.TCorp; import java.io.File;
import java.io.FileOutputStream; public class PDFReport {
private static TCorp tCorp; Document document = new Document();// 建立一个Document对象 public PDFReport(String out) {
try {
File file = new File(out);
file.createNewFile();
Rectangle pageSize = new Rectangle(PageSize.A4);
document.setPageSize(pageSize);
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
PDFBuilder builder = new PDFBuilder();
writer.setPageEvent(builder);
document.open();
PdfPTable table = generatePDF();
document.add(table);
document.close();
} catch (Exception e) {
e.printStackTrace();
}
} public static void settCorp(TCorp tCorp) {
PDFReport.tCorp = tCorp;
} public PdfPTable generatePDF() {
//设置单元格为5列
PdfPTable table = PDFUtil.createTable(5); table.addCell(PDFUtil.createHeadCell("企业信息列表"));
table.addCell(PDFUtil.createTitleCell_1("企业名称"));
table.addCell(PDFUtil.createCell_1(tCorp.getCorpName()));
table.addCell(PDFUtil.createTitleCell_1("联系方式"));
table.addCell(PDFUtil.createCell_1(tCorp.getCorpTel()));
table.addCell(PDFUtil.createCell_2("Logo")); table.addCell(PDFUtil.createTitleCell_1("企业邮箱"));
table.addCell(PDFUtil.createCell_1(tCorp.getCorpEmail()));
table.addCell(PDFUtil.createTitleCell_1("网址"));
table.addCell(PDFUtil.createCell_1(tCorp.getCorpWebUrl())); table.addCell(PDFUtil.createTitleCell_1("企业地址"));
table.addCell(PDFUtil.createCell_1(tCorp.getCorpAddr()));
table.addCell(PDFUtil.createTitleCell_1("注册/实缴"));
table.addCell(PDFUtil.createCell_1(String.valueOf(tCorp.getRegCapi())+"万 / "+String.valueOf(tCorp.getPaidCapi())+"万")); table.addCell(PDFUtil.createTitleCell_1("成立日期"));
table.addCell(PDFUtil.createCell_1(tCorp.getStartDate()));
table.addCell(PDFUtil.createTitleCell_1("统一社会信用代码"));
table.addCell(PDFUtil.createCell_3(tCorp.getUniScid())); table.addCell(PDFUtil.createTitleCell_1("法定代表人"));
table.addCell(PDFUtil.createCell_1(tCorp.getOperManName()));
table.addCell(PDFUtil.createTitleCell_1("纳税人识别号"));
table.addCell(PDFUtil.createCell_3(tCorp.getTaxpayNum())); table.addCell(PDFUtil.createTitleCell_1("注册号"));
table.addCell(PDFUtil.createCell_1(tCorp.getRegNo()));
table.addCell(PDFUtil.createTitleCell_1("组织机构代码"));
table.addCell(PDFUtil.createCell_3(tCorp.getOrgInstCode())); table.addCell(PDFUtil.createTitleCell_1("公司类型"));
table.addCell(PDFUtil.createCell_1(tCorp.getEconKind()));
table.addCell(PDFUtil.createTitleCell_1("人员规模"));
table.addCell(PDFUtil.createCell_3(tCorp.getStaffSize())); table.addCell(PDFUtil.createTitleCell_1("营业期限"));
table.addCell(PDFUtil.createCell_1(tCorp.getFareTermStart()+" 至 "+tCorp.getFareTermEnd()));
table.addCell(PDFUtil.createTitleCell_1("登记机关"));
table.addCell(PDFUtil.createCell_3(tCorp.getBelongOrg())); table.addCell(PDFUtil.createTitleCell_1("核准日期"));
table.addCell(PDFUtil.createCell_1(tCorp.getCheckDate()));
table.addCell(PDFUtil.createTitleCell_1("所属行业"));
table.addCell(PDFUtil.createCell_3(tCorp.getBelongTrade())); table.addCell(PDFUtil.createTitleCell_1("英文名称"));
table.addCell(PDFUtil.createCell_1(tCorp.getEnglishName()));
table.addCell(PDFUtil.createTitleCell_1("曾用名"));
table.addCell(PDFUtil.createCell_3(tCorp.getFormerName())); table.addCell(PDFUtil.createTitleCell_2("经营范围"));
table.addCell(PDFUtil.createCell_4(tCorp.getFareScope())); return table;
}
}

3、PDFUtil类中设置字体、表格样式、以及水印文字样式,setColspan函数为设置所跨列数,setRowspan函数为设置所跨行数:

 package util;

 import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*; import javax.imageio.ImageIO;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream; public class PDFUtil {
private static Font headfont ; // 设置字体大小
private static Font keyfont; // 设置字体大小
private static Font textfont; // 设置字体大小 static{
BaseFont bfChinese;
try {
bfChinese = BaseFont.createFont("STSong-Light","UniGB-UCS2-H",BaseFont.NOT_EMBEDDED);
headfont = new Font(bfChinese, 24, Font.BOLD,BaseColor.BLACK);// 设置字体大小
keyfont = new Font(bfChinese, 12, Font.BOLD,BaseColor.BLACK);// 设置字体大小
textfont = new Font(bfChinese, 10, Font.NORMAL,BaseColor.BLACK);// 设置字体大小
} catch (Exception e) {
e.printStackTrace();
}
} //表格标题
public static PdfPCell createHeadCell(String value){
PdfPCell cell = new PdfPCell();
cell.setVerticalAlignment(15);
cell.setHorizontalAlignment(15);
cell.setColspan(5);
cell.setPhrase(new Phrase(value,headfont));
cell.setHorizontalAlignment(Element.ALIGN_CENTER); //水平居中
cell.setPadding(10.0f);
cell.setBorder(0);
cell.setPaddingTop(5.0f);
cell.setPaddingBottom(18.0f);
return cell;
} //表格表头样式1
public static PdfPCell createTitleCell_1(String value){
PdfPCell cell = new PdfPCell();
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
cell.setPhrase(new Phrase(value, keyfont));
cell.setBackgroundColor(new BaseColor(29, 181, 238));
cell.setColspan(1);
cell.setFixedHeight(35);
return cell;
} //表格表头样式2
public static PdfPCell createTitleCell_2(String value){
PdfPCell cell = new PdfPCell();
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
cell.setPhrase(new Phrase(value, keyfont));
cell.setBackgroundColor(new BaseColor(29, 181, 238));
cell.setColspan(1);
cell.setRowspan(3);
cell.setFixedHeight(105);
return cell;
} //表格内容样式1
public static PdfPCell createCell_1(String value){
PdfPCell cell = new PdfPCell();
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
cell.setPhrase(new Phrase(value,textfont));
cell.setBackgroundColor(new BaseColor(255, 255, 255));
cell.setColspan(1);
cell.setFixedHeight(35);
return cell;
} //表格内容样式2
public static PdfPCell createCell_2(String value){
PdfPCell cell = new PdfPCell();
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
cell.setPhrase(new Phrase(value,textfont));
cell.setBackgroundColor(new BaseColor(255, 255, 255));
cell.setColspan(1);
cell.setRowspan(3);
cell.setFixedHeight(105);
return cell;
} //表格内容样式3
public static PdfPCell createCell_3(String value){
PdfPCell cell = new PdfPCell();
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
cell.setPhrase(new Phrase(value,textfont));
cell.setBackgroundColor(new BaseColor(255, 255, 255));
cell.setColspan(2);
cell.setFixedHeight(35);
return cell;
} //表格内容样式4
public static PdfPCell createCell_4(String value){
PdfPCell cell = new PdfPCell();
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
cell.setPhrase(new Phrase(value,textfont));
cell.setBackgroundColor(new BaseColor(255, 255, 255));
cell.setColspan(4);
cell.setRowspan(3);
cell.setFixedHeight(105);
return cell;
} //生成表格
public static PdfPTable createTable(int colNumber){
int widths[] = { 35,40,35,35,30 };
PdfPTable baseTable = new PdfPTable(colNumber);
baseTable.setWidthPercentage(100);
baseTable.setSpacingBefore(10);
try {
baseTable.setWidths(widths);
} catch (DocumentException e) {
e.printStackTrace();
}
return baseTable;
} public static void addImage(String input,String output,String realPath) throws Exception{
BufferedOutputStream out = new BufferedOutputStream(
new FileOutputStream(new File(output)));
PdfReader reader = new PdfReader(input);
PdfStamper stamper = new PdfStamper(reader, out);
addWatermark(stamper,"测试添加水印文字");
int total = reader.getNumberOfPages();
try {
Image image = Image.getInstance(realPath);
image.setAbsolutePosition(350, 200);
image.scaleToFit(160, 70);
PdfContentByte content= stamper.getOverContent(total);// 在内容上方加水印
content.addImage(image);
}catch (Exception e){
e.printStackTrace();
} stamper.close();
reader.close();
} public static void addWatermark(PdfStamper pdfStamper, String waterMarkName) throws Exception {
PdfContentByte content;
BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H",
BaseFont.NOT_EMBEDDED);
Rectangle pageRect;
PdfGState gs = new PdfGState();
try {
if (base == null || pdfStamper == null) {
return;
}
// 设置透明度为0.4
gs.setFillOpacity(0.3f);
gs.setStrokeOpacity(0.3f);
int toPage = pdfStamper.getReader().getNumberOfPages();
for (int i = 1; i <= toPage; i++) {
pageRect = pdfStamper.getReader().getPageSizeWithRotation(i);
// 计算水印X,Y坐标
float x = pageRect.getWidth() / 2;
float y = pageRect.getHeight() / 2;
// 获得PDF最顶层
content = pdfStamper.getOverContent(i);
content.saveState();
// set Transparency
content.setGState(gs);
content.beginText();
content.setColorFill(BaseColor.GRAY);
content.setFontAndSize(base, 30);
// 水印文字成45度角倾斜
content.showTextAligned(Element.ALIGN_CENTER, waterMarkName, x,
y, 45);
content.endText();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}

4、PDFBuilder类中为设置页面附加属性:

 package util;

 import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*; import java.io.IOException; public class PDFBuilder extends PdfPageEventHelper {
/**
* 页眉
*/
public String header = ""; /**
* 文档字体大小,页脚页眉最好和文本大小一致
*/
public int presentFontSize = 12; // 模板
public PdfTemplate total; // 基础字体对象
public BaseFont bf = null; // 利用基础字体生成的字体对象,一般用于生成中文文字
public Font fontDetail = null; /**
*
* Creates a new instance of PdfReportM1HeaderFooter 无参构造方法.
*
*/
public PDFBuilder() { } public void setHeader(String header) {
this.header = header;
} /**
*
* TODO 文档打开时创建模板
*
* @see com.itextpdf.text.pdf.PdfPageEventHelper#onOpenDocument(com.itextpdf.text.pdf.PdfWriter,
* com.itextpdf.text.Document)
*/
public void onOpenDocument(PdfWriter writer, Document document) {
total = writer.getDirectContent().createTemplate(50, 50);// 共 页 的矩形的长宽高
} /**
*
* TODO 关闭每页的时候,写入页眉,写入'第几页共'这几个字。
*
* @see com.itextpdf.text.pdf.PdfPageEventHelper#onEndPage(com.itextpdf.text.pdf.PdfWriter,
* com.itextpdf.text.Document)
*/
public void onEndPage(PdfWriter writer, Document document) {
this.addPage(writer, document);
} //加分页
public void addPage(PdfWriter writer, Document document){
try {
if (bf == null) {
bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);
}
if (fontDetail == null) {
fontDetail = new Font(bf, presentFontSize, Font.NORMAL);// 数据体字体
}
} catch (DocumentException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} // 1.写入页眉
ColumnText.showTextAligned(writer.getDirectContent(),
Element.ALIGN_LEFT, new Phrase(header, fontDetail),
document.left(), document.top() + 20, 0);
// 2.写入前半部分的 第 X页/共
int pageS = writer.getPageNumber();
String foot1 = "第 " + pageS + " 页 / 共";
Phrase footer = new Phrase(foot1, fontDetail); // 3.计算前半部分的foot1的长度,后面好定位最后一部分的'Y页'这俩字的x轴坐标,字体长度也要计算进去 = len
float len = bf.getWidthPoint(foot1, presentFontSize); // 4.拿到当前的PdfContentByte
PdfContentByte cb = writer.getDirectContent(); // 5.写入页脚1,x轴就是(右margin+左margin + right() -left()- len)/2.0F
// 再给偏移20F适合人类视觉感受,否则肉眼看上去就太偏左了
// ,y轴就是底边界-20,否则就贴边重叠到数据体里了就不是页脚了;注意Y轴是从下往上累加的,最上方的Top值是大于Bottom好几百开外的。
ColumnText
.showTextAligned(
cb,
Element.ALIGN_CENTER,
footer,
(document.rightMargin() + document.right()
+ document.leftMargin() - document.left() - len) / 2.0F + 20F,
document.bottom() - 20, 0); // 6.写入页脚2的模板(就是页脚的Y页这俩字)添加到文档中,计算模板的和Y轴,X=(右边界-左边界 - 前半部分的len值)/2.0F +
// len , y 轴和之前的保持一致,底边界-20
cb.addTemplate(total, (document.rightMargin() + document.right()
+ document.leftMargin() - document.left()) / 2.0F + 20F,
document.bottom() - 20); // 调节模版显示的位置 } /**
*
* TODO 关闭文档时,替换模板,完成整个页眉页脚组件
*
* @see com.itextpdf.text.pdf.PdfPageEventHelper#onCloseDocument(com.itextpdf.text.pdf.PdfWriter,
* com.itextpdf.text.Document)
*/
public void onCloseDocument(PdfWriter writer, Document document) {
// 7.最后一步,是关闭文档的时候,将模板替换成实际的 Y 值,至此,page x of y 制作完毕,完美兼容各种文档size。
total.beginText();
total.setFontAndSize(bf, presentFontSize);// 生成的模版的字体、颜色
String foot2 = " " + (writer.getPageNumber()-1) + " 页";
total.showText(foot2);// 模版显示的内容
total.endText();
total.closePath();
}
}

最后附上生成的PDF效果图:

本文学习参考了:https://blog.csdn.net/qq_30490591/article/details/53434777

至此是关于JavaWeb项目生成PDF文件添加水印图片并导出,仅供参考。

如有疏漏错误之处,还请不吝赐教!

JavaWeb项目生成PDF文件添加水印图片并导出的更多相关文章

  1. Java给图片和PDF文件添加水印(图片水印和文字水印)

    有时候我们看到的图片或者PDF文件会自动加上水印.分为文字水印和图片水印. ----------------------------图片水印---------------------------- 1 ...

  2. 怎么用PHP在HTML中生成PDF文件

    原文:Generate PDF from html using PHP 译文:使用PHP在html中生成PDF 译者:dwqs 利用PHP编码生成PDF文件是一个非常耗时的工作.在早期,开发者使用PH ...

  3. 【使用Itext处理PDF文档(新建PDF文件、修改PDF文件、PDF中插入图片、将PDF文件转换为图片)】

    iText简介 iText是著名的开放源码的站点sourceforge一个项目,是用于生成PDF文档的一个java类库.通过iText不仅可以生成PDF或rtf的文档,而且可以将XML.Html文件转 ...

  4. Itext生成pdf文件

    来源:https://my.oschina.net/lujianing/blog/894365 1.背景 在某些业务场景中,需要提供相关的电子凭证,比如网银/支付宝中转账的电子回单,签约的电子合同等. ...

  5. C#生成PDF文件流

    1.设置字体 static BaseFont FontBase = BaseFont.CreateFont("C:\\WINDOWS\\FONTS\\STSONG.TTF", Ba ...

  6. C# 给PDF文件添加水印

      水印种类及功能介绍 PDF水印分为两种:文本水印和图片水印.文本水印一般被用在商业领域,提醒读者该文档是受版权保护的,其他人不能抄袭或者免费使用.除了这个特征,水印还可以用来标记这个文档 的一些基 ...

  7. asp.net生成PDF文件 (1)

    asp.net生成PDF文件 (1) 这个是例子是网上淘来的,哈哈,很有用的! 首先要到网上下载itextsharp.dll,然后添加引用,主程序如下: 1 2 3 4 5 6 7 8 9 10 11 ...

  8. JAVA生成PDF文件

    生成PDF文件是主要应用的是ITEXT插件 import java.awt.Color; import java.io.File; import java.io.FileOutputStream; i ...

  9. java调用wkhtmltopdf生成pdf文件,美观,省事

    最近项目需要导出企业风险报告,文件格式为pdf,于是搜了一大批文章都是什么Jasper Report,iText ,flying sauser ,都尝试了一遍,感觉不是我想要的效果, 需要自己调整好多 ...

随机推荐

  1. 交叉熵Cross-Entropy

    1.交叉熵:用来描述通信中将一个概率分布的最优编码用到另一个概率分布的平均比特数 公式: 2.交叉熵是不对称的 3.交叉熵的作用是表达两个概率分布的差异性 设概率分布p(x)和q(x),两个概率分布差 ...

  2. MVC 实现下拉框

    MVC动态实现下拉框的方式有很多种,但是方便快捷的却是很少,现在记录一种常用的下拉框实现方式: 1.先看看视图代码是怎么写的 <div class="form-group col-xs ...

  3. C# 控制台模拟序列化和反序列化

    序列化:将对象转换成二进制串的过程 反序列化:将序列化过程中产生的二进制串转换成对象的过程 作用:传输数据 using System; namespace WriteTextContent { [Se ...

  4. Objective-C中的@dynamic与@synthesize的区别

    Objective-C中的@dynamic 转自:http://blog.csdn.net/haishu_zheng/article/details/12873151 一.@dynamic与@synt ...

  5. Knowledge Point 20180305 Java程序员详述编码Unicode

    Unicode Unicode(统一码.万国码.单一码)是计算机科学领域里的一项业界标准,包括字符集.编码方案等.Unicode 是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设 ...

  6. mvc上传图片(上传和预览)webuploader

    笔者看到mvc最近比较流行,而很多使用一些比较旧的的方法上传图片,再次安利一下百度的webuploader控件吧 webuploader第一步要先下载一些插件这点可以在webuploader官网上下载 ...

  7. GitHub Desktop 拉取 GitHub上 Tag 版本代码

    一直在使用 GitHub Desktop 图形化 git 管理工具,统一项目框架版本时需要切换到ThinkPHP Tag 分支版本,步骤如下, 1,先在 GitHub 中找到需要的版本,点进去 2,点 ...

  8. vscode调试html文件

    1. vscode调试html文件 1.1. 使用Debugger for Chrome进行调试 1.1.1. 基于本地file配置方式调试 1.1.2. 基于服务端配置方式调试 1.1.2.1. 启 ...

  9. 关于CoreLocation定位服务的简单使用

    在我们发微博,发表空间内容,以及在朋友圈发表动态的时候,会发现有一个位置信息的控件.iOS中是如何定位我们的位置信息的呢?基于此写一个小Demo,供大家参考使用. 在iOS中,用于定位时需要我们导入以 ...

  10. qq空间认证教程:借助企鹅媒体平台认证QQ公众空间

    年轻人,最近你是否眼看众多新开的QQ空间认证成功,自己却一筹莫展,而心情极度狂躁焦虑,别急,以下是详细教程,不能保证100%,但老夫已认证成功几个号. 不废话,直接上流程: 方法大致有2种: 1. 通 ...