最近做了一个项目使用Android手机打印excel表,现在把自己的心得分享给大家。

一、项目需求:

表格内容固定,不同的用户,每条信息打分不同,生成表格后打印出来盖章。

二、开发背景:

1、android系统自带打印功能,但是只能打印图片或者pdf

2、打印机使用的是 HP OfficeJet 200,打印机具有WI-FI Direct功能,可以在没有网络,没有电源的情况下便携打印

(机器本身就是一个路由器,android设备需要连接wifi至该打印机,android设备需要安装HP打印服务插件服务)

3、android设备中需要提前安装Hp Print Service插件

4、需要在项目assets目录中放入一个通用excel表

三、展示:(下面那个是原表,上面这个是打印出来的)

四、使用框架:

excel表编辑工具jxl.jar

网络rxvolley

五、关键代码:

package com.axin.wifiprint;import android.Manifest;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.print.PrintAttributes;
import android.print.PrintManager;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;import com.kymjs.rxvolley.RxVolley;
import com.kymjs.rxvolley.client.HttpCallback;
import com.kymjs.rxvolley.client.ProgressListener;import java.io.File;
import java.io.InputStream;
import java.util.List;import jxl.Workbook;
import jxl.write.WritableCell;
import jxl.write.WritableSheet;public class MainActivity extends AppCompatActivity {private WifiManager mWifiManager;private TextView error_tv;private WifiConnector connector;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);error_tv= (TextView) findViewById(R.id.error_tv);findViewById(R.id.click1).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {try {InputStream open = getResources().getAssets().open("分数表.xls");Workbook workbook = Workbook.getWorkbook(open);// 分数表.xls 得到的对象是只读的,// 如果要修改Excel,需要创建一个可读的副本,副本指向原Excel文件(即下面的new File())File file = new File(Environment.getExternalStoragePublicDirectory("Download") + "/分数表.xls");if (file.exists()) {file.delete();}file.createNewFile();//创建workbook的副本jxl.write.WritableWorkbook wbe = Workbook.createWorkbook(file, workbook);//获取第一个sheetWritableSheet sheet = wbe.getSheet(0);//获取第四列、第七行单元格,在我这里就是张三5的成绩WritableCell cell = sheet.getWritableCell(3, 6);//获取这个单元格的格式jxl.format.CellFormat cf = cell.getCellFormat();// Label(x,y,z) 代表单元格的第x+1列,第y+1行, 内容z// 在Label对象的子对象中指明单元格的位置和内容//第四列、第七行,在我这里就是张三5的成绩jxl.write.Label lbl = new jxl.write.Label(3, 6, "90");//将修改后的单元格的格式设定成跟原来一样lbl.setCellFormat(cf);//将改过的单元格保存到sheetsheet.addCell(lbl);//将修改保存到workbook --》一定要保存wbe.write();//关闭workbook,释放内存 ---》一定要释放内存wbe.close();} catch (Exception e) {e.printStackTrace();}}});findViewById(R.id.click2).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//让你的后台帮你写一个excel转码成pdf的文件,然后下载下来并保存/** 这里我要特别说明的是:* 1、安卓系统内,没有任何可以使用的框架,直接将excel转为pdf文件* 2、wps安卓版可以转码是因为他们与microsoft公司签署了协议,他们能够拿到excel的数据转码方式* 3、wps没有给我们免费提供转码的框架或接口* 4、我们可以使用itext5框架 手动绘制pdf文件,说实话很麻烦。而且文档都是外文的。有兴趣的同学可以参考* 地址:https://developers.itextpdf.com/content/itext-5-examples* 5、因此最简单的方法就是上传至自己的后台,只要服务器安装了microsoft office,后台代码还是很简单的(不做解释)*///等待加载框showDialog();RxVolley.download(Environment.getExternalStoragePublicDirectory("Download") + "/分数表.pdf","http://app1.lnbhjg.com/handlers/APK/fenshubiao.pdf",new ProgressListener() {@Overridepublic void onProgress(long transferredBytes, long totalSize) {if (transferredBytes == totalSize) {hideDialog();Toast.makeText(MainActivity.this, "可以打印了", Toast.LENGTH_SHORT).show();}}}, new HttpCallback() {@Overridepublic void onSuccess(String t) {super.onSuccess(t);}@Overridepublic void onFailure(int errorNo, String strMsg) {super.onFailure(errorNo, strMsg);hideDialog();Toast.makeText(MainActivity.this, "服务器请求失败", Toast.LENGTH_SHORT).show();}});}});mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);findViewById(R.id.click3).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {showDialog();if (!mWifiManager.isWifiEnabled()) {mWifiManager.setWifiEnabled(true);try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}checkPemision();}});}private void checkPemision(){//在checkCallerCanAccessScanResults中检查了ACCESS_FINE_LOCATION和ACCESS_COARSE_LOCATION//如果没有这两个权限,就会返回一个empty Listif (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED &&ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {// 申请一个(或多个)权限,并提供用于回调返回的获取码(用户定义)Toast.makeText(MainActivity.this, "开启定位权限,才能使用打印功能", Toast.LENGTH_SHORT).show();ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.ACCESS_FINE_LOCATION}, 102);} else {openList();}} else {openList();}}private Handler handler=new Handler(){@Overridepublic void handleMessage(Message msg) {hideDialog();switch (msg.what){case 90:error_tv.setVisibility(View.VISIBLE);break;case 91:print();break;case 92:error_tv.setVisibility(View.VISIBLE);break;}}};//HP OfficeJet200打印机 拥有WI-FI Direct功能 可以在没有网络 没有电源的情况下便携打印//特点是:机器本身就是个路由器,用户通过Android通过wifi链接至该打印机 然后便能轻松打印//wifiprivate void openList() {if(isHasHPNet()){connector=new WifiConnector(mWifiManager,handler);connector.connect("DIRECT-98-HP OfficeJet 200","12345678", WifiConnector.WifiCipherType.WIFICIPHER_WPA);}else {Toast.makeText(MainActivity.this, "请打开HP OfficeJet 200打印机后重试", Toast.LENGTH_SHORT).show();}}private boolean isHasHPNet(){List<ScanResult> scanResults = mWifiManager.getScanResults();for(ScanResult result:scanResults){if(result.SSID.equals("DIRECT-98-HP OfficeJet 200")){return true;}}return false;}@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);if (requestCode == 102) {if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {openList();} else {// 没有获取到权限,做特殊处理hideDialog();error_tv.setVisibility(View.VISIBLE);Toast.makeText(MainActivity.this, "请按照打印说明继续完成打印功能", Toast.LENGTH_SHORT).show();}}}private void print() {PrintManager printManager = (PrintManager) getSystemService(Context.PRINT_SERVICE);PrintAttributes.Builder builder = new PrintAttributes.Builder();builder.setColorMode(PrintAttributes.COLOR_MODE_COLOR);//第一个参数是任务名称(随便起一个)printManager.print("print1",new MyPrintAdapter(this, Environment.getExternalStoragePublicDirectory("Download") + "/分数表.pdf"), builder.build());}//    加载progressdialog初始化private ProgressDialog dialog;private void showDialog() {if (dialog == null) {dialog = new ProgressDialog(this);dialog.setMessage("请等待...");dialog.setCancelable(false);}dialog.show();}private void hideDialog() {if (dialog != null) {dialog.dismiss();}}}
package com.axin.wifiprint;/*** Created by Administrator on 2018/1/9.*/import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.pdf.PdfDocument;
import android.graphics.pdf.PdfDocument.PageInfo;
import android.graphics.pdf.PdfRenderer;
import android.os.Build;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.ParcelFileDescriptor;
import android.print.PageRange;
import android.print.PrintAttributes;
import android.print.PrintDocumentAdapter;
import android.print.PrintDocumentInfo;
import android.print.pdf.PrintedPdfDocument;
import android.support.annotation.RequiresApi;import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;/****/
public class MyPrintAdapter extends PrintDocumentAdapter {private Context context;private int pageHeight;private int pageWidth;private PdfDocument mPdfDocument;private int totalpages = 1;private String pdfPath;private List<Bitmap> mlist;public MyPrintAdapter(Context context,String pdfPath) {this.context = context;this.pdfPath = pdfPath;}@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)@Overridepublic void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal,LayoutResultCallback callback,Bundle metadata) {mPdfDocument = new PrintedPdfDocument(context, newAttributes); //创建可打印PDF文档对象pageHeight = newAttributes.getMediaSize().ISO_A4.getHeightMils() * 72 / 1000;  //设置尺寸pageWidth = newAttributes.getMediaSize().ISO_A4.getWidthMils() * 72 / 1000;if (cancellationSignal.isCanceled()) {callback.onLayoutCancelled();return;}ParcelFileDescriptor mFileDescriptor = null;PdfRenderer pdfRender = null;PdfRenderer.Page page = null;try {mFileDescriptor = ParcelFileDescriptor.open(new File(pdfPath), ParcelFileDescriptor.MODE_READ_ONLY);if (mFileDescriptor != null)pdfRender = new PdfRenderer(mFileDescriptor);mlist = new ArrayList<>();if (pdfRender.getPageCount() > 0) {totalpages = pdfRender.getPageCount();for (int i = 0; i < pdfRender.getPageCount(); i++) {if(null != page)page.close();page = pdfRender.openPage(i);Bitmap bmp = Bitmap.createBitmap(page.getWidth()*2,page.getHeight()*2, Bitmap.Config.ARGB_8888);page.render(bmp, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);mlist.add(bmp);}}if(null != page)page.close();if(null != mFileDescriptor)mFileDescriptor.close();if (null != pdfRender)pdfRender.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}if (totalpages > 0) {PrintDocumentInfo.Builder builder = new PrintDocumentInfo.Builder("分数表.pdf").setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT).setPageCount(totalpages);  //构建文档配置信息PrintDocumentInfo info = builder.build();callback.onLayoutFinished(info, true);} else {callback.onLayoutFailed("Page count is zero.");}}@Overridepublic void onWrite(final PageRange[] pageRanges, final ParcelFileDescriptor destination, final CancellationSignal cancellationSignal,final WriteResultCallback callback) {for (int i = 0; i < totalpages; i++) {if (pageInRange(pageRanges, i)) //保证页码正确{PageInfo newPage = new PageInfo.Builder(pageWidth,pageHeight, i).create();PdfDocument.Page page =mPdfDocument.startPage(newPage);  //创建新页面if (cancellationSignal.isCanceled()) {  //取消信号callback.onWriteCancelled();mPdfDocument.close();mPdfDocument = null;return;}drawPage(page, i);  //将内容绘制到页面Canvas上mPdfDocument.finishPage(page);}}try {mPdfDocument.writeTo(new FileOutputStream(destination.getFileDescriptor()));} catch (IOException e) {callback.onWriteFailed(e.toString());return;} finally {mPdfDocument.close();mPdfDocument = null;}callback.onWriteFinished(pageRanges);}private boolean pageInRange(PageRange[] pageRanges, int page) {for (int i = 0; i < pageRanges.length; i++) {if ((page >= pageRanges[i].getStart()) &&(page <= pageRanges[i].getEnd()))return true;}return false;}//页面绘制(渲染)private void drawPage(PdfDocument.Page page,int pagenumber) {Canvas canvas = page.getCanvas();if(mlist != null){Paint paint = new Paint();Bitmap bitmap = mlist.get(pagenumber);int bitmapWidth = bitmap.getWidth();int bitmapHeight = bitmap.getHeight();// 计算缩放比例float scale = (float)pageWidth/(float)bitmapWidth;// 取得想要缩放的matrix参数Matrix matrix = new Matrix();matrix.postScale(scale, scale);canvas.drawBitmap(bitmap,matrix,paint);}}}
package com.axin.wifiprint;import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.AuthAlgorithm;
import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.text.TextUtils;import java.util.List;public class WifiConnector {Handler handler;WifiManager wifiManager;//WIFICIPHER_WEP是WEP ,WIFICIPHER_WPA是WPA,WIFICIPHER_NOPASS没有密码public enum WifiCipherType {WIFICIPHER_WEP, WIFICIPHER_WPA, WIFICIPHER_NOPASS, WIFICIPHER_INVALID}// 构造函数public WifiConnector(WifiManager wifiManager,Handler handler) {this.wifiManager = wifiManager;this.handler = handler;}// 提供一个外部接口,传入要连接的无线网public void connect(String ssid, String password, WifiCipherType type) {Thread thread = new Thread(new ConnectRunnable(ssid, password, type));thread.start();}// 查看以前是否也配置过这个网络private WifiConfiguration isExsits(String SSID) {List<WifiConfiguration> existingConfigs = wifiManager.getConfiguredNetworks();for (WifiConfiguration existingConfig : existingConfigs) {if (existingConfig.SSID.equals("\"" + SSID + "\"")) {return existingConfig;}}return null;}private WifiConfiguration createWifiInfo(String SSID, String Password,WifiCipherType Type) {WifiConfiguration config = new WifiConfiguration();config.allowedAuthAlgorithms.clear();config.allowedGroupCiphers.clear();config.allowedKeyManagement.clear();config.allowedPairwiseCiphers.clear();config.allowedProtocols.clear();config.SSID = "\"" + SSID + "\"";// nopassif (Type == WifiCipherType.WIFICIPHER_NOPASS) {config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);}// wepif (Type == WifiCipherType.WIFICIPHER_WEP) {if (!TextUtils.isEmpty(Password)) {if (isHexWepKey(Password)) {config.wepKeys[0] = Password;} else {config.wepKeys[0] = "\"" + Password + "\"";}}config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);config.allowedKeyManagement.set(KeyMgmt.NONE);config.wepTxKeyIndex = 0;}// wpaif (Type == WifiCipherType.WIFICIPHER_WPA) {config.preSharedKey = "\"" + Password + "\"";config.hiddenSSID = true;config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);// 此处需要修改否则不能自动重联// config.allowedProtocols.set(WifiConfiguration.Protocol.WPA);config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);config.status = WifiConfiguration.Status.ENABLED;}return config;}class ConnectRunnable implements Runnable {private String ssid;private String password;private WifiCipherType type;public ConnectRunnable(String ssid, String password, WifiCipherType type) {this.ssid = ssid;this.password = password;this.type = type;}@Overridepublic void run() {try {// 开启wifi功能需要一段时间(我在手机上测试一般需要1-3秒左右),所以要等到wifi// 状态变成WIFI_STATE_ENABLED的时候才能执行下面的语句
//                while (wifiManager.getWifiState() == WifiManager.WIFI_STATE_ENABLING) {
//                    try {
//                        // 为了避免程序一直while循环,让它睡个100毫秒检测……
//                        Thread.sleep(100);
//                    } catch (InterruptedException ie) {
//                    }
//                }WifiConfiguration wifiConfig = createWifiInfo(ssid, password,type);//if (wifiConfig == null) {handler.sendEmptyMessage(90);return;}WifiConfiguration tempConfig = isExsits(ssid);if (tempConfig != null) {wifiManager.removeNetwork(tempConfig.networkId);}//                int netID = wifiManager.addNetwork(wifiConfig);
//                boolean enabled = wifiManager.enableNetwork(netID, true);
//                sendMsg("enableNetwork status enable=" + enabled);
//                boolean connected = wifiManager.reconnect();
//                sendMsg("enableNetwork connected=" + connected);
//                sendMsg("连接成功!");handler.sendEmptyMessage(91);} catch (Exception e) {// TODO: handle exceptionhandler.sendEmptyMessage(92);e.printStackTrace();}}}private static boolean isHexWepKey(String wepKey) {final int len = wepKey.length();// WEP-40, WEP-104, and some vendors using 256-bit WEP (WEP-232?)if (len != 10 && len != 26 && len != 58) {return false;}return isHex(wepKey);}private static boolean isHex(String key) {for (int i = key.length() - 1; i >= 0; i--) {final char c = key.charAt(i);if (!(c >= '0' && c <= '9' || c >= 'A' && c <= 'F' || c >= 'a'&& c <= 'f')) {return false;}}return true;}
}

下载demo: 项目地址(现在下载的项目没法设置免费了,有需要的可以留邮箱)

Android excel表打印相关推荐

  1. 设置Excel表打印时的表头和页码

    设置Excel表打印时的表头和页码 如果没有设置Excel表的表头和页码,打印的Excel表是下面这种样子 只有第一页有表头,其后的页都没有表头,并且都没有页码,表格很不美观,也不知道到底有多少页,不 ...

  2. excel设置打印区域_仅在没有打印区域的情况下打印Excel表

    excel设置打印区域 Today, we'll look at a time-saving Table trick that you might not know about. See how to ...

  3. pb更新oracle表格,PB自定义retrieve刷新函数、PB导入excel表、打印

    2013年12月30日 //定义一个打印工作 long job //打开打印设置 job = PrintOpen("一份数据文档") //指定打印数据窗口 PrintDataWin ...

  4. Microsoft Excel 教程「3」:如何在 Excel 中打印工作表?

    欢迎观看 Microsoft Excel 教程,小编带大家学习 Microsoft Excel 的使用技巧,了解如何在 Excel 中打印工作表. 可打印全部或部分工作表,可一次打印一个,也可一次打印 ...

  5. Java poi 导出excel 设置将整个工作表打印在一页 打印机设置

    // 创建excel文件对象 HSSFWorkbook wb = new HSSFWorkbook(); // 创建sheetSheet sheet = wb.createSheet("sh ...

  6. Android 的Excel表的数据导出

    前言 用Android 把一些数据用Excel表导出 一.引入jxl库? 1.直接引用 implementation group: 'net.sourceforge.jexcelapi', name: ...

  7. JSP设置Excel表格换行_Excel表格技巧—如何调整工作表打印页面设置

    在我们平时使用excel表格时,除了要学会各种不同的工作表技能,有关最后文件打印输出的页面设置也必须掌握.为了让大家更加清晰明了的了解,我们一起学习一下如何调整工作表打印页面设置. 首先打开一个exc ...

  8. brother标签打印软件_标签打印软件如何导入excel表批量制作光缆标牌

    光缆标牌是贴在光缆线上的标识牌,一般记录着该光缆的起始位置和结束位置,以及当前光缆的线长,有了光缆标牌可以使人了解该光缆线的具体情况,以及方便后期维修人员对光缆线的维修检测.那么一般的光缆标牌是如何批 ...

  9. excel实现套用模板批量打印_标签打印软件如何导入excel表批量制作光缆标牌

    光缆标牌是贴在光缆线上的标识牌,一般记录着该光缆的起始位置和结束位置,以及当前光缆的线长,有了光缆标牌可以使人了解该光缆线的具体情况,以及方便后期维修人员对光缆线的维修检测.那么一般的光缆标牌是如何批 ...

最新文章

  1. 2015化妆品行业如何进行微信公众号营销
  2. Qt + VS 【如何添加图片资源】
  3. python的应用领域-Python的应用领域
  4. Java培训总结:过滤器链的实现方法、配置和案例分析
  5. android 毕业设计 文献翻译,android毕业设计外文翻译.doc
  6. hadoop伪分布式搭建 java_hadoop2.2.0伪分布式搭建
  7. php aes 3des区别,AES和3DES之间的区别
  8. C#托管代码调用C++非托管代码
  9. 计算机一级在线练习,计算机一级练习系统
  10. SQL*Plus环境下创建PLUSTRACE角色
  11. Win10解决Android Studio:Gradle sync failed: Failed to open zip file.
  12. ffmpeg 最简单的转码封装mp4文件
  13. unity用代码生成的物体或line renderer让其在确定的某一个层里面的方法
  14. 毕设题目:Matlab图像重建
  15. 汽车电子嵌入式软件概述
  16. python实现图片拼接长图_用Python实现长截图拼接
  17. python实现模拟登录云课堂智慧职教并获取课程信息(1)
  18. IDEA中如何进行XML解析
  19. 怎么查看笔记本内存条型号_笔记本如何加内存条之如何查看笔记本内存品牌和型号...
  20. wuc-tab标签点击不了_微信公众号新增标签功能,格力被中国移动取消竞标资格,全国电子无偿献血证上线,QQ新增辣椒酱表情,这就是今天的其他大新闻!...

热门文章

  1. unity 游戏内大额数值换算K、M、B、T
  2. 源码安装GCC-4.9.2
  3. 做IP 还是做自己?
  4. notepad++ smali语法高亮模板分享
  5. Spring入门教程
  6. java毕业设计校园课室资源预约系统设计与实现mybatis+源码+调试部署+系统+数据库+lw
  7. java调用asmx接口_java调用.net写的webserver接口(.asmx后缀)
  8. JAVA电商项目面试题(一)
  9. LAMP架构搭建明细,源码编译安装
  10. JS三元表达式多条件写法