27.5.2 文件操作模块
文件操作模块实现三个功能,即打开文件、保存当前文件和打印文件。这里不涉及复杂的算法,但是对于Swing控件的使用会对读者很有帮助。对于文件模块的三个操作对应的菜单和工具栏快捷工具在主界面设计中已经完成,这里只需要设置监听器,在监听器中编写相应的处理代码。
1.打开文件操作
【实例27.3】打开文件的代码如下所示。
01 //为openbutton按钮注册监听器
02 openbutton.addActionListener(new ActionListener(){
03 public void actionPerformed(ActionEvent event){
04 JFileChooser c=new JFileChooser();
05 //创建文件过滤器,打开文件对话框时在文件类型中只显示".xls"文件类型
06 c.addChoosableFileFilter(new ExcelFileFilter());
07 c.showOpenDialog(null);
08 //GetOwnerNumber类提供一个对话框,提示用户输入当前话单的用户名或手机号
09 GetOwnerNumber geton=new GetOwnerNumber(getthis());
10 try{
11 int ivalue=0;
12 if(ivalue==JFileChooser.APPROVE_OPTION){
13 //将GetOwnerNumber类对象放置在主界面的中心位置
14 geton.setLocation(((int)getthis().getLocation().getX()+getthis().getWidth()/2)-
15 geton.getWidth()/2,((int)getthis().getLocation().getY()+getthis().getHeight()
16 /2)-geton.getHeight()/2);
17 geton.show();
18 String filename=null;
19 String filedirectory=null;
20 file_and_directoryname=null;
21 //获得用户选择的文件名
22 filename=c.getSelectedFile().getName();
23 //获得用户选择的文件目录
24 filedirectory=c.getCurrentDirectory().toString();
25 //把该目录和文件传给ReadAndAnalyzeDataTread
26 file_and_directoryname=filedirectory+"\"+filename;
27 getInputISWorkbook(file_and_directoryname);
28 }
29 }
30 catch(Exception ex)
31 {
32 JOptionPane.showMessageDialog(null,"取消该次保存");
33 geton.dispose();
34 }
35 }
36 }
37);
38 openbutton.addMouseListener(new MouseAdapter(){
39 public void mouseEntered(MouseEvent event){
40 textfield.setText("当前功能提示:打开已经保存的话单Excel文件,此时要求输入话单用户
41 的手机号码,以方便识别该用户。");
42 }
43 public void mouseExited(MouseEvent event){
44 textfield.setText("当前状态提示");
45 }
46 }
47);
【代码说明】上述代码完成打开对话框的功能,在该程序中,用户单击打开文件对话框的“打开”按钮后不会立即读入话单文件,而是先打开提示用户输入用户名或用户号码的对话框,只有单击该对话框中的“确定”按钮才打开话单的Excel表格,并将其显示在用户界面上。
打开文件对话框如图27.9所示。当用户单击打开文件对话框中的“打开”按钮时,会弹出如图27.10所示的获得用户号码对话框。
图 27.9 打开文件对话框
图 27.10 用户号码输入对话框
此时用户单击“确定”按钮,程序会调用一个线程读取话单文件的内容并显示在用户主界面上。接下来会介绍如何实现读取Excel表格数据的类和方法。
【实例27.4】在打开文件代码中涉及文件过滤的功能,该功能很好地满足了用户对于过滤特定文件的需要,该文件过滤功能类的实现主要是继承javax.swing.filechooser.FileFilter类,覆写其getDescription()方法。该类的实现如下所示。
01 class ExcelFileFilter extends javax.swing.filechooser.FileFilter{
02 public boolean accept(File file){
03 if(file.isDirectory()||file.getPath().toLowerCase().endsWith(".xls"))
04 return true;
05 else
06 return false;
07 }
08 public String getDescription(){
09 return".xls";
10 }
11 }
【代码说明】第1行说明该类继承自FileFilter类,第8~10行书写覆盖getDescription()的代码。在打开文件代码中还涉及getInputISWorkbook()方法,该方法的具体实现如下所示。
01 public void getInputISWorkbook(String path){
02 wb=null;
03 try{
04 //获得文件输入流
05 InputStream is=new FileInputStream(path);
06 //获得工作簿对象
07 this.wb=Workbook.getWorkbook(is);
08 sheetname=null;
09 //通过工作簿对象获得Excel文件中第一个表单的名字
10 sheetname=wb.getSheet(0).getName();
11 }
12 catch(Exception ex){
13 ex.printStackTrace();
14 }
15 }
【代码说明】该方法通过用户选择的路径和文件名称,获得文件输入流对象,通过Workbook的静态方法getWorkbook(InputStream is)获得一个工作簿对象,通过该对象来读取当前Excel表中话单的对应信息。
【实例27.5】刚才我们讲过,一旦用户单击图27.10中的“确定”按钮,程序会启动一个新的线程通过工作簿对象wb来读取话单Excel表格中的数据信息。这里主要分析一下程序中的一个读取数据的线程,名称为ReadAndAnalyzeDataTread。该线程的主要功能体现在一个方法readandanalyzesheetdata()上,如下所示。
01 private void readandanalyzesheetdata(){
02 //获得当前Excel表的第一个表单对象
03 jxl.Sheet st=(window.wb).getSheet(0);
04 //获得当前Excel表的第一个表单的行数
05 int sheetrow=st.getRows();
06 //获得当前Excel表的第一个表单的列数
07 int sheetcolumn=st.getColumns();
08 //通过当前Excel表的第一个表单的行和列数读取表单中每个cell的数据,并根据数据类型
09 //作了相应的数据类型的转换
10 for(int i=0;i<sheetrow;i++){
11 rowdata1=null;
12 Cell[]datacell=st.getRow(i);
13 rowdata1=new Object[datacell.length+1];
14 for(int j=0;j<datacell.length;j++){
15 //判断CellType是否为日期类型
16 if(datacell[j].getType()==CellType.DATE){
17 TimeZone gmtZone=TimeZone.getTimeZone("GMT");
18 SimpleDateFormat format=new SimpleDateFormat("yyyy/MM/dd hh:mm");
19 format.setTimeZone(gmtZone);
20 DateCell dateCell=(DateCell)datacell[3];
21 String dateString=format.format(dateCell.getDate());
22 System.out.println(dateString);
23 rowdata1[j+1]=dateString;
24 }
25 //判断CellType是否为数字类型
26 if(datacell[j].getType()==CellType.NUMBER){
27 NumberCell nc=(NumberCell)datacell[j];
28 rowdata1[j+1]=new Double(nc.getValue());
29 }
30 else
31 rowdata1[j+1]=datacell[j].getContents();
32 }
33 rowdata1[0]=window.ownernumber;
34 //向用户主界面中增加一行数据
35 window.shoujimodel.addRow(rowdata1);
36 //对每列数据分析数据类型,然后按响应的数据类型处理
37 }
38 }
【代码说明】上述代码读取话单Excel表格中的数据信息,在读取时,需要判断表格中的各列的数据类型。第16行的CellType.DATE判断是否是日期型,第26行的CellType.NUMBER判断是否是数字型。
2.保存文件的实现
保存文件首先需要打开一个保存文件的对话框,用户输入文件名,文件自动保存为Excel文件。这里有两个关键点,一个是打开文件对话框的实现,另一个是如何把当前的经过处理(排序、关联处理等)的话单数据写入到用户命名的Excel文件中。
【实例27.6】首先介绍保存文件对话框,程序如下所示。
01 savebutton.addActionListener(new ActionListener(){
02 public void actionPerformed(ActionEvent event){
03 //创建JFileChooser对象c
04 JFileChooser c=new JFileChooser();
05 //通过JFileChooser对象c为其增加一个文件过滤器对象,只允许保存为Excel文件
06 c.addChoosableFileFilter(new ExcelFileFilter());
07 //打开保存文件对话框
08 c.showSaveDialog(null);
09 try{
10 int ivalue=0;
11 if(ivalue==JFileChooser.APPROVE_OPTION){
12 //如果用户单击了"保存"按钮,则执行以下代码,首先是获得用户输入的文件名,而后创建线
13 //程类SaveTableData对象,并启动该线程来向用户输入的文件中写入数据
14 File f=c.getSelectedFile();
15 String filename=c.getName(f);
16 savedirectoryandfilename=f.toString();
17 SaveTableData savethread=new SaveTableData(getthis());
18 savethread.run();
19 }
20 }
21 catch(Exception ex){
22 OptionPane.showMessageDialog(null,"您没有选择存储路径,取消该次保存!
23 ");
24 }
25 c.setVisible(false);
26 }
27 }
28);
29 savebutton.addMouseListener(new MouseAdapter(){
30 public void mouseEntered(MouseEvent event){
31 //注册鼠标监听器,一旦鼠标滑过保存按钮时,则在文本框textfield中显示提示信息
32 textfield.setText("当前功能提示:保存当前的表单为Excel表,默认保存为两张表,
33 分为"固话"表和"手机"表。");
34 }
35 public void mouseExited(MouseEvent event){
36 textfield.setText("当前状态提示");
37 }
38 }
39);
【代码说明】上例演示了打开文件对话框的事件监听器,通过该监听器的处理使用户可以方便地为文件命名,并保存当前的话单文件。
打开的保存文件对话框如图27.11所示。
图 27.11 保存当前文件对话框
用户一旦单击“保存”按钮,程序会启动一个写数据线程类SaveTableData向用户定义的Excel文件中写入数据。
【实例27.7】下面分析一下如何实现向Excel表中写入数据,在该类中笔者设计了一个方法processShoujiTableData()来完成写数据的功能,如下代码所示的方法。
01 private void processShoujiTableData(){
02 //获得用户选择存储保存后的文件的目录和文件名,创建文件对象f
03 File f=new File(window.savedirectoryandfilename+".xls");
04 //下面try区块中的代码实现向Excel表格中写入当前话单的数据
05 try{
06 //创建新的工作簿对象
07 WritableWorkbook workbook=Workbook.createWorkbook(f);
08 //通过工作簿对象创建新的话单对象
09 WritableSheet sheet=workbook.createSheet("第一页",0);
10 //获得当前需要保存的话单的行数
11 int row=saveshoujitable.getRowCount();
12 //获得当前需要保存的话单的列数
13 int column=saveshoujitable.getColumnCount();
14 //获得当前话单的表头信息作为列名
15 for(int j=0;j<column;j++){
16 String columnname=saveshoujitable.getColumnName(j);
17 Label l=new Label(j,0,columnname);
18 sheet.addCell(l);
19 }
20 //依次把当前话单的数据写入新创建的话单对象sheet
21 for(int i=1;i<row+1;i++){
22 for(int j=0;j<column;j++){
23 Label l=new Label(j, i,saveshoujitable.getValueAt(i-1,j).toString());
24 sheet.addCell(l);
25 }
26 }
27 sheet.setColumnView(80,80);
28 //将数据写入工作簿对象,即写入用户命名的Excel文件
29 workbook.write();
30 //关闭工作簿对象,停止向文件中的写操作
31 workbook.close();
32 }
33 catch(Exception ex){
34 ex.printStackTrace();
35 }
36 }
【代码说明】第3行获得用户选择存储保存后的文件名。第6~9行创建话单对象,第11~13行获取表格的行数和列数。第15~26行通过两个循环获取单元格信息。
3.打印操作
【实例27.8】首先看如何打开打印文件对话框。这里主要通过一个按钮监听器实现。
01 printitem.addActionListener(new ActionListener(){
02 public void actionPerformed(ActionEvent event){
03 PrintService[]services=PrintServiceLookup.lookupPrintServices(null, null);
04 PrintService svc=PrintServiceLookup.lookupDefaultPrintService();
05 PrintRequestAttributeSet attrset=new HashPrintRequestAttributeSet();
06 PrintService selection=ServiceUI.printDialog(null,100,100,services, svc, null, attrset);
07 }
08 }
09);
【代码说明】具体实现打印当前的文件这里不再详细介绍,读者只要参考任何一本关于讲解“打印”操作的资料都可以获得。
一旦单击“打印”按钮将弹出对话框,如图27.12所示。