`
53873039oycg
  • 浏览: 824788 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

[整理]docx4j创建简单表格示例

 
阅读更多

       原文见:http://programmingbb.blogspot.com/2014/08/using-docx4j-to-generate-docx-files.html .下面的代码稍微修改了下:

      

import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import java.io.File;
import java.io.FileInputStream;
import java.math.BigInteger;

import org.apache.commons.io.IOUtils;
import org.docx4j.dml.wordprocessingDrawing.Inline;
import org.docx4j.jaxb.Context;
import org.docx4j.model.structure.PageDimensions;
import org.docx4j.model.structure.PageSizePaper;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage;
import org.docx4j.wml.Body;
import org.docx4j.wml.BooleanDefaultTrue;
import org.docx4j.wml.CTBorder;
import org.docx4j.wml.CTShd;
import org.docx4j.wml.CTTblPrBase.TblStyle;
import org.docx4j.wml.CTVerticalJc;
import org.docx4j.wml.Color;
import org.docx4j.wml.Drawing;
import org.docx4j.wml.HpsMeasure;
import org.docx4j.wml.Jc;
import org.docx4j.wml.JcEnumeration;
import org.docx4j.wml.ObjectFactory;
import org.docx4j.wml.P;
import org.docx4j.wml.PPr;
import org.docx4j.wml.R;
import org.docx4j.wml.RFonts;
import org.docx4j.wml.RPr;
import org.docx4j.wml.STBorder;
import org.docx4j.wml.STVerticalJc;
import org.docx4j.wml.SectPr;
import org.docx4j.wml.SectPr.PgMar;
import org.docx4j.wml.Tbl;
import org.docx4j.wml.TblPr;
import org.docx4j.wml.TblWidth;
import org.docx4j.wml.Tc;
import org.docx4j.wml.TcMar;
import org.docx4j.wml.TcPr;
import org.docx4j.wml.TcPrInner.GridSpan;
import org.docx4j.wml.TcPrInner.TcBorders;
import org.docx4j.wml.TcPrInner.VMerge;
import org.docx4j.wml.Text;
import org.docx4j.wml.Tr;
import org.docx4j.wml.U;
import org.docx4j.wml.UnderlineEnumeration;

//原文见:http://programmingbb.blogspot.com/2014/08/using-docx4j-to-generate-docx-files.html
public class Docx4j_创建表格_S5_Test {
	public static void main(String[] args) throws Exception {
		Docx4j_创建表格_S5_Test t = new Docx4j_创建表格_S5_Test();
		t.testDocx4jCreateTable();
	}

	public void testDocx4jCreateTable() throws Exception {
		boolean landscape = false;
		WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage
				.createPackage(PageSizePaper.A4, landscape);
		ObjectFactory factory = Context.getWmlObjectFactory();
		setPageMargins(wordMLPackage, factory);
		String imgFilePath = "f:/saveFile/tmp/2sql日志.jpg";
		Tbl table = createTableWithContent(wordMLPackage, factory, imgFilePath);
		wordMLPackage.getMainDocumentPart().addObject(table);
		wordMLPackage.save(new File("f:/saveFile/temp/sys_"
				+ System.currentTimeMillis() + ".docx"));
	}

	public Tbl createTableWithContent(WordprocessingMLPackage wordMLPackage,
			ObjectFactory factory, String imgFilePath) throws Exception {
		Tbl table = factory.createTbl();
		// for TEST: this adds borders to all cells
		TblPr tblPr = new TblPr();
		TblStyle tblStyle = new TblStyle();
		tblStyle.setVal("TableGrid");
		tblPr.setTblStyle(tblStyle);
		table.setTblPr(tblPr);
		Tr tableRow = factory.createTr();
		// a default table cell style
		Docx4jStyle_S3 defStyle = new Docx4jStyle_S3();
		defStyle.setBold(false);
		defStyle.setItalic(false);
		defStyle.setUnderline(false);
		defStyle.setHorizAlignment(JcEnumeration.CENTER);
		// a specific table cell style
		Docx4jStyle_S3 style = new Docx4jStyle_S3();
		style.setBold(true);
		style.setItalic(true);
		style.setUnderline(true);
		style.setFontSize("40");
		style.setFontColor("FF0000");
		style.setCnFontFamily("微软雅黑");
		style.setEnFontFamily("Times New Roman");
		style.setTop(300);
		style.setBackground("CCFFCC");
		style.setVerticalAlignment(STVerticalJc.CENTER);
		style.setHorizAlignment(JcEnumeration.CENTER);
		style.setBorderTop(true);
		style.setBorderBottom(true);
		style.setNoWrap(true);
		addTableCell(factory, tableRow, "测试Field 1", 3500, style, 1, null);
		// start vertical merge for Filed 2 and Field 3 on 3 rows
		addTableCell(factory, tableRow, "测试Field 2", 3500, defStyle, 1,
				"restart");
		addTableCell(factory, tableRow, "测试Field 3", 1500, defStyle, 1,
				"restart");
		table.getContent().add(tableRow);
		tableRow = factory.createTr();
		addTableCell(factory, tableRow, "Text", 3500, defStyle, 1, null);
		addTableCell(factory, tableRow, "", 3500, defStyle, 1, "");
		addTableCell(factory, tableRow, "", 1500, defStyle, 1, "");
		table.getContent().add(tableRow);
		tableRow = factory.createTr();
		addTableCell(factory, tableRow, "Interval", 3500, defStyle, 1, null);
		addTableCell(factory, tableRow, "", 3500, defStyle, 1, "close");
		addTableCell(factory, tableRow, "", 1500, defStyle, 1, "close");
		table.getContent().add(tableRow);
		// add an image horizontally merged on 3 cells
		String filenameHint = null;
		String altText = null;
		int id1 = 0;
		int id2 = 1;
		byte[] bytes = getImageBytes(imgFilePath);
		P pImage;
		try {
			pImage = newImage(wordMLPackage, factory, bytes, filenameHint,
					altText, id1, id2, 8500);
			tableRow = factory.createTr();
			addTableCell(factory, tableRow, pImage, 8500, defStyle, 3, null);
			table.getContent().add(tableRow);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return table;
	}

	public byte[] getImageBytes(String imgFilePath) throws Exception {
		return IOUtils.toByteArray(new FileInputStream(imgFilePath));
	}

	public void addTableCell(ObjectFactory factory, Tr tableRow, P image,
			int width, Docx4jStyle_S3 style, int horizontalMergedCells,
			String verticalMergedVal) {
		Tc tableCell = factory.createTc();
		addImageCellStyle(tableCell, image, style);
		setCellWidth(tableCell, width);
		setCellVMerge(tableCell, verticalMergedVal);
		setCellHMerge(tableCell, horizontalMergedCells);
		tableRow.getContent().add(tableCell);
	}

	public void addTableCell(ObjectFactory factory, Tr tableRow,
			String content, int width, Docx4jStyle_S3 style,
			int horizontalMergedCells, String verticalMergedVal) {
		Tc tableCell = factory.createTc();
		addCellStyle(factory, tableCell, content, style);
		setCellWidth(tableCell, width);
		setCellVMerge(tableCell, verticalMergedVal);
		setCellHMerge(tableCell, horizontalMergedCells);
		if (style.isNoWrap()) {
			setCellNoWrap(tableCell);
		}
		tableRow.getContent().add(tableCell);
	}

	public void addCellStyle(ObjectFactory factory, Tc tableCell,
			String content, Docx4jStyle_S3 style) {
		if (style != null) {
			P paragraph = factory.createP();
			Text text = factory.createText();
			text.setValue(content);
			R run = factory.createR();
			run.getContent().add(text);
			paragraph.getContent().add(run);
			setHorizontalAlignment(paragraph, style.getHorizAlignment());
			RPr runProperties = factory.createRPr();
			if (style.isBold()) {
				addBoldStyle(runProperties);
			}
			if (style.isItalic()) {
				addItalicStyle(runProperties);
			}
			if (style.isUnderline()) {
				addUnderlineStyle(runProperties);
			}
			setFontSize(runProperties, style.getFontSize());
			setFontColor(runProperties, style.getFontColor());
			setFontFamily(runProperties, style.getCnFontFamily(),style.getEnFontFamily());
			setCellMargins(tableCell, style.getTop(), style.getRight(),
					style.getBottom(), style.getLeft());
			setCellColor(tableCell, style.getBackground());
			setVerticalAlignment(tableCell, style.getVerticalAlignment());
			setCellBorders(tableCell, style.isBorderTop(),
					style.isBorderRight(), style.isBorderBottom(),
					style.isBorderLeft());
			run.setRPr(runProperties);
			tableCell.getContent().add(paragraph);
		}
	}

	public void addImageCellStyle(Tc tableCell, P image, Docx4jStyle_S3 style) {
		setCellMargins(tableCell, style.getTop(), style.getRight(),
				style.getBottom(), style.getLeft());
		setCellColor(tableCell, style.getBackground());
		setVerticalAlignment(tableCell, style.getVerticalAlignment());
		setHorizontalAlignment(image, style.getHorizAlignment());
		setCellBorders(tableCell, style.isBorderTop(), style.isBorderRight(),
				style.isBorderBottom(), style.isBorderLeft());
		tableCell.getContent().add(image);
	}

	public P newImage(WordprocessingMLPackage wordMLPackage,
			ObjectFactory factory, byte[] bytes, String filenameHint,
			String altText, int id1, int id2, long cx) throws Exception {
		BinaryPartAbstractImage imagePart = BinaryPartAbstractImage
				.createImagePart(wordMLPackage, bytes);
		Inline inline = imagePart.createImageInline(filenameHint, altText, id1,
				id2, cx, false);
		// Now add the inline in w:p/w:r/w:drawing
		P p = factory.createP();
		R run = factory.createR();
		p.getContent().add(run);
		Drawing drawing = factory.createDrawing();
		run.getContent().add(drawing);
		drawing.getAnchorOrInline().add(inline);
		return p;
	}

	public void setCellBorders(Tc tableCell, boolean borderTop,
			boolean borderRight, boolean borderBottom, boolean borderLeft) {
		TcPr tableCellProperties = tableCell.getTcPr();
		if (tableCellProperties == null) {
			tableCellProperties = new TcPr();
			tableCell.setTcPr(tableCellProperties);
		}
		CTBorder border = new CTBorder();
		// border.setColor("auto");
		border.setColor("0000FF");
		border.setSz(new BigInteger("20"));
		border.setSpace(new BigInteger("0"));
		border.setVal(STBorder.SINGLE);
		TcBorders borders = new TcBorders();
		if (borderBottom) {
			borders.setBottom(border);
		}
		if (borderTop) {
			borders.setTop(border);
		}
		if (borderLeft) {
			borders.setLeft(border);
		}
		if (borderRight) {
			borders.setRight(border);
		}
		tableCellProperties.setTcBorders(borders);
	}

	public void setCellWidth(Tc tableCell, int width) {
		if (width > 0) {
			TcPr tableCellProperties = tableCell.getTcPr();
			if (tableCellProperties == null) {
				tableCellProperties = new TcPr();
				tableCell.setTcPr(tableCellProperties);
			}
			TblWidth tableWidth = new TblWidth();
			tableWidth.setType("dxa");
			tableWidth.setW(BigInteger.valueOf(width));
			tableCellProperties.setTcW(tableWidth);
		}
	}

	public void setCellNoWrap(Tc tableCell) {
		TcPr tableCellProperties = tableCell.getTcPr();
		if (tableCellProperties == null) {
			tableCellProperties = new TcPr();
			tableCell.setTcPr(tableCellProperties);
		}
		BooleanDefaultTrue b = new BooleanDefaultTrue();
		b.setVal(true);
		tableCellProperties.setNoWrap(b);
	}

	public void setCellVMerge(Tc tableCell, String mergeVal) {
		if (mergeVal != null) {
			TcPr tableCellProperties = tableCell.getTcPr();
			if (tableCellProperties == null) {
				tableCellProperties = new TcPr();
				tableCell.setTcPr(tableCellProperties);
			}
			VMerge merge = new VMerge();
			if (!"close".equals(mergeVal)) {
				merge.setVal(mergeVal);
			}
			tableCellProperties.setVMerge(merge);
		}
	}

	public void setCellHMerge(Tc tableCell, int horizontalMergedCells) {
		if (horizontalMergedCells > 1) {
			TcPr tableCellProperties = tableCell.getTcPr();
			if (tableCellProperties == null) {
				tableCellProperties = new TcPr();
				tableCell.setTcPr(tableCellProperties);
			}
			GridSpan gridSpan = new GridSpan();
			gridSpan.setVal(new BigInteger(String
					.valueOf(horizontalMergedCells)));
			tableCellProperties.setGridSpan(gridSpan);
			tableCell.setTcPr(tableCellProperties);
		}
	}

	public void setCellColor(Tc tableCell, String color) {
		if (color != null) {
			TcPr tableCellProperties = tableCell.getTcPr();
			if (tableCellProperties == null) {
				tableCellProperties = new TcPr();
				tableCell.setTcPr(tableCellProperties);
			}
			CTShd shd = new CTShd();
			shd.setFill(color);
			tableCellProperties.setShd(shd);
		}
	}

	public void setCellMargins(Tc tableCell, int top, int right, int bottom,
			int left) {
		TcPr tableCellProperties = tableCell.getTcPr();
		if (tableCellProperties == null) {
			tableCellProperties = new TcPr();
			tableCell.setTcPr(tableCellProperties);
		}
		TcMar margins = new TcMar();
		if (bottom > 0) {
			TblWidth bW = new TblWidth();
			bW.setType("dxa");
			bW.setW(BigInteger.valueOf(bottom));
			margins.setBottom(bW);
		}
		if (top > 0) {
			TblWidth tW = new TblWidth();
			tW.setType("dxa");
			tW.setW(BigInteger.valueOf(top));
			margins.setTop(tW);
		}
		if (left > 0) {
			TblWidth lW = new TblWidth();
			lW.setType("dxa");
			lW.setW(BigInteger.valueOf(left));
			margins.setLeft(lW);
		}
		if (right > 0) {
			TblWidth rW = new TblWidth();
			rW.setType("dxa");
			rW.setW(BigInteger.valueOf(right));
			margins.setRight(rW);
		}
		tableCellProperties.setTcMar(margins);
	}

	public void setVerticalAlignment(Tc tableCell, STVerticalJc align) {
		if (align != null) {
			TcPr tableCellProperties = tableCell.getTcPr();
			if (tableCellProperties == null) {
				tableCellProperties = new TcPr();
				tableCell.setTcPr(tableCellProperties);
			}
			CTVerticalJc valign = new CTVerticalJc();
			valign.setVal(align);
			tableCellProperties.setVAlign(valign);
		}
	}

	public void setFontSize(RPr runProperties, String fontSize) {
		if (fontSize != null && !fontSize.isEmpty()) {
			HpsMeasure size = new HpsMeasure();
			size.setVal(new BigInteger(fontSize));
			runProperties.setSz(size);
			runProperties.setSzCs(size);
		}
	}

	public void setFontFamily(RPr runProperties, String cnFontFamily,String enFontFamily) {
		if (cnFontFamily != null||enFontFamily!=null) {
			RFonts rf = runProperties.getRFonts();
			if (rf == null) {
				rf = new RFonts();
				runProperties.setRFonts(rf);
			}
			if(cnFontFamily!=null){
				rf.setEastAsia(cnFontFamily);
			}
			if(enFontFamily!=null){
				rf.setAscii(enFontFamily);
			}
		}
	}

	public void setFontColor(RPr runProperties, String color) {
		if (color != null) {
			Color c = new Color();
			c.setVal(color);
			runProperties.setColor(c);
		}
	}

	public void setHorizontalAlignment(P paragraph, JcEnumeration hAlign) {
		if (hAlign != null) {
			PPr pprop = new PPr();
			Jc align = new Jc();
			align.setVal(hAlign);
			pprop.setJc(align);
			paragraph.setPPr(pprop);
		}
	}

	public void addBoldStyle(RPr runProperties) {
		BooleanDefaultTrue b = new BooleanDefaultTrue();
		b.setVal(true);
		runProperties.setB(b);
	}

	public void addItalicStyle(RPr runProperties) {
		BooleanDefaultTrue b = new BooleanDefaultTrue();
		b.setVal(true);
		runProperties.setI(b);
	}

	public void addUnderlineStyle(RPr runProperties) {
		U val = new U();
		val.setVal(UnderlineEnumeration.SINGLE);
		runProperties.setU(val);
	}

	public void setPageMargins(WordprocessingMLPackage wordMLPackage,
			ObjectFactory factory) {
		try {
			Body body = wordMLPackage.getMainDocumentPart().getContents()
					.getBody();
			PageDimensions page = new PageDimensions();
			PgMar pgMar = page.getPgMar();
			pgMar.setBottom(BigInteger.valueOf(pixelsToDxa(50)));
			pgMar.setTop(BigInteger.valueOf(pixelsToDxa(50)));
			pgMar.setLeft(BigInteger.valueOf(pixelsToDxa(50)));
			pgMar.setRight(BigInteger.valueOf(pixelsToDxa(50)));
			SectPr sectPr = factory.createSectPr();
			body.setSectPr(sectPr);
			sectPr.setPgMar(pgMar);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// get dots per inch
	public static int getDPI() {
		return GraphicsEnvironment.isHeadless() ? 96 : Toolkit
				.getDefaultToolkit().getScreenResolution();
	}

	public int pixelsToDxa(int pixels) {
		return (1440 * pixels / getDPI());
	}
}

class Docx4jStyle_S3 {
	private boolean bold;
	private boolean italic;
	private boolean underline;
	private String fontSize;
	private String fontColor;
	private String cnFontFamily;
	private String enFontFamily;
	// cell margins
	private int left;
	private int bottom;
	private int top;
	private int right;
	private String background;
	private STVerticalJc verticalAlignment;
	private JcEnumeration horizAlignment;
	private boolean borderLeft;
	private boolean borderRight;
	private boolean borderTop;
	private boolean borderBottom;
	private boolean noWrap;

	public boolean isBold() {
		return bold;
	}

	public void setBold(boolean bold) {
		this.bold = bold;
	}

	public boolean isItalic() {
		return italic;
	}

	public void setItalic(boolean italic) {
		this.italic = italic;
	}

	public boolean isUnderline() {
		return underline;
	}

	public void setUnderline(boolean underline) {
		this.underline = underline;
	}

	public String getFontSize() {
		return fontSize;
	}

	public void setFontSize(String fontSize) {
		this.fontSize = fontSize;
	}

	public String getFontColor() {
		return fontColor;
	}

	public void setFontColor(String fontColor) {
		this.fontColor = fontColor;
	}

	public String getCnFontFamily() {
		return cnFontFamily;
	}

	public void setCnFontFamily(String cnFontFamily) {
		this.cnFontFamily = cnFontFamily;
	}

	public String getEnFontFamily() {
		return enFontFamily;
	}

	public void setEnFontFamily(String enFontFamily) {
		this.enFontFamily = enFontFamily;
	}

	public int getLeft() {
		return left;
	}

	public void setLeft(int left) {
		this.left = left;
	}

	public int getBottom() {
		return bottom;
	}

	public void setBottom(int bottom) {
		this.bottom = bottom;
	}

	public int getTop() {
		return top;
	}

	public void setTop(int top) {
		this.top = top;
	}

	public int getRight() {
		return right;
	}

	public void setRight(int right) {
		this.right = right;
	}

	public String getBackground() {
		return background;
	}

	public void setBackground(String background) {
		this.background = background;
	}

	public STVerticalJc getVerticalAlignment() {
		return verticalAlignment;
	}

	public void setVerticalAlignment(STVerticalJc verticalAlignment) {
		this.verticalAlignment = verticalAlignment;
	}

	public JcEnumeration getHorizAlignment() {
		return horizAlignment;
	}

	public void setHorizAlignment(JcEnumeration horizAlignment) {
		this.horizAlignment = horizAlignment;
	}

	public boolean isBorderLeft() {
		return borderLeft;
	}

	public void setBorderLeft(boolean borderLeft) {
		this.borderLeft = borderLeft;
	}

	public boolean isBorderRight() {
		return borderRight;
	}

	public void setBorderRight(boolean borderRight) {
		this.borderRight = borderRight;
	}

	public boolean isBorderTop() {
		return borderTop;
	}

	public void setBorderTop(boolean borderTop) {
		this.borderTop = borderTop;
	}

	public boolean isBorderBottom() {
		return borderBottom;
	}

	public void setBorderBottom(boolean borderBottom) {
		this.borderBottom = borderBottom;
	}

	public boolean isNoWrap() {
		return noWrap;
	}

	public void setNoWrap(boolean noWrap) {
		this.noWrap = noWrap;
	}
}

 

    结果为:

    

 

    全文完。

  • 大小: 45.3 KB
0
0
分享到:
评论

相关推荐

    docx4j 动态生成表格 (一 )

    NULL 博文链接:https://01jiangwei01.iteye.com/blog/2123504

    docx4j-3.3.5-API文档-中英对照版.zip

    赠送jar包:docx4j-3.3.5.jar; 赠送原API文档:docx4j-3.3.5-javadoc.jar; 赠送源代码:docx4j-3.3.5-sources.jar; 赠送Maven依赖信息文件:docx4j-3.3.5.pom; 包含翻译后的API文档:docx4j-3.3.5-javadoc-API...

    docx4j-3.3.5-API文档-中文版.zip

    赠送jar包:docx4j-3.3.5.jar; 赠送原API文档:docx4j-3.3.5-javadoc.jar; 赠送源代码:docx4j-3.3.5-sources.jar; 赠送Maven依赖信息文件:docx4j-3.3.5.pom; 包含翻译后的API文档:docx4j-3.3.5-javadoc-API...

    DOCX4J jar包

    docx4j 用的jar包,docx4j学习网址:http://www.docx4java.org/trac/docx4j

    docx4j项目(包括jar包、javadoc文档、源码及示例)

    资源中包含docx4j项目的jar包(及主要依赖Jar)、javadoc、源码和示例等,因为花费挺大力气整理出来,所以定了2分,如果您有需要而缺少CSDN下载,请留言或发短消息索取.... 另外,请关注我的博客,其中有些对docx4j...

    最新 docx4j-master

    最新 docx4j-master最新 docx4j-master最新 docx4j-master最新 docx4j-master最新 docx4j-master最新 docx4j-master最新 docx4j-master最新 docx4j-master最新 docx4j-master最新 docx4j-master最新 docx4j-master...

    docx4j及其依赖包

    docx4j支持操作后缀.docx得word文档,替换书签,获取文档内容,稳定资源

    docx4j相关jar包

    docx4j运行需要的jar包,这里是整理好的所有必须的jar包

    docx4j操作word

    docx4j操作word,主要使用docx4j对word进行操作,比如chart图表、标签替换、目录等。

    用docx4j操作word书签,在word书签中插入文本

    用docx4j,jar出去word书签,在word书签中插入文本 源码可以通过以下链接查看: https://github.com/xulp-mzl/xlp-core https://github.com/xulp-mzl/xlp-third ...实例: public static void main(String[] args) ...

    docx4j所需jar包全

    docx4j所需jar包整合,其中word转pdf,word转html,word中docx转doc,java代码实现,都可以使用,仅限学习参考使用。

    利用docx4j实现docx转pdf

    利用docx4j实现docx转pdf小dome

    使用docx4j 技术操作word的读写

    使用docx4J技术操作word的读写,使用docx4J技术操作word的读写,

    docx4j生成word文档

    最近在做一个出卷系统,需要通过试卷模板从数据库中抽取题目,然后按照模板的样式生成完整的试卷,包括试卷格式的排版和图片的写入。这是用docx4j生成word文档。里面包括完整代码和所需jar包。

    java实现多个docx文档合并(基于docx4j)

    java实现word的合并,jdk版本1.7,直接导入eclipse中即可。基于docx4j3.3.3实现。内含所有jar包,MargeDoc中含有主方法

    docx4J 文件源代码 docx4J 2.2.2 source files

    docx4J 文件源代码 docx4J source files docx4j is an open source Java library for manipulating OpenXML WordprocessingML documents, released under the Apache software licence. docx is the default file ...

    docx4j api

    docx4j api 帮助文档 word导出必备 学习必备

    docx4j项目(javadoc文档、源码及示例)

    docx4j是Java操作office2007+中的Word、Excel、PPT的开源项目,其主要针对WordXML同时也可以处理Excel和PPT,比POI要强大很多

Global site tag (gtag.js) - Google Analytics