请教一个数据输出的问题,麻烦大家帮忙看看!!

lsh902 2009-11-26 05:34:08
问题:IO输出多个字段,取的三张表的字段也不一样,1.如何在输出的文件表中添加String类型的相应组长的字段???要求要和表1、表2、表3的字段相对应!!!
2.如何先先输出第一行标题,然后再循环输出表的内容??3.如何添加一列字段计算合计:(业务量*单价)??4.怎样将null值显示为没有值??输出为:
组长 业务量 单价 员工编号 经理 地区 合计
组长1 A B C null null A*B
.... .. ... ... ... ... ...
组长2 D E F null G D*E
.... ... .. .. ... ... ...
组长3 H I J K null H*I
.... .. .. ... ... ... ...


import java.sql.*;
import java.util.*;
import java.io.*;

public class test extends ClassObj{
public static void main(String[] args) throws Exception {
try {
ArrayList<ClassObj> lst = test.getResultLst();
String contents = test.formatLst(lst);
String fileName = "C:\\result.txt";
test.saveFile(fileName, contents);
} catch (Exception e) {
e.printStackTrace();
}
}
static ArrayList<ClassObj> getResultLst() throws Exception {
String url = "jdbc:odbc:study";
String user = "sa";
String password = "123";
ArrayList <ClassObj> lst = new ArrayList <ClassObj>();
Connection con = null;
Connection con2 = null;
Connection con3 = null;
PreparedStatement pstmt = null;

ResultSet rs = null;
ResultSet rs2 = null;
ResultSet rs3 = null;
String sql = "select 业务量 as A,单价 as B,员工编号 as C from 表1";
String sql2 = "select 业务量 as D,单价 as E,员工编号 as F,地区 as G from 表2";
String sql3 = "select 业务量 as H,单价 as I,员工编号 as J,经理 as K from 表3";
try{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
con = DriverManager.getConnection(url,user,password);

pstmt = con.prepareStatement(sql);
pstmt2 = con.prepareStatement(sql2);
pstmt3 = con.prepareStatement(sql3);
rs = pstmt.executeQuery();
rs2 = pstmt2.executeQuery();
rs3 = pstmt3.executeQuery();
String fa = "组长1";
String fb = "组长2";
String fc = "组长3";

ClassObj c1=null;
while(rs.next()){ //怎样将fa,fb,fc跟相应的rs,rs2,rs3对应循环输出。
c1=new ClassObj(); //c1.setBand(rs.getString("fa"));?????
c1.setBuss(rs.getDouble("A"));
c1.setPrice(rs.getDouble("B"));
c1.setId(rs.getString("C"));
//怎么才能计算合并输出????
//c1.setId(rs.getDouble(A*B));
lst.add(c1);
}
while(rs2.next()){
c1=new ClassObj();
c1.setBuss(rs.getDouble("D"));
c1.setPrice(rs.getDouble("E"));
c1.setId(rs.getString("F"));
c1.setLand(rs.getString("G"));
lst.add(c1);
}
while(rs3.next()){
c1=new ClassObj();
c1.setBuss(rs.getDouble("H"));
c1.setPrice(rs.getDouble("I"));
c1.setId(rs.getString("J"));
c1.setMan(rs.getString("K"));
lst.add(c1);
}

}catch(Exception e){
e.printStackTrace();
}finally{
try{
if (rs != null)
rs.close();
if (pstmt != null)
pstmt.close();
if (con != null)
con.close();

}catch(Exception e){}
}
}
static void saveFile(String fileName, String contents)
throws IOException {
File f = new File(fileName);

if (f.exists()){
throw new IOException("file exists...");
}
if (!f.createNewFile()) {
throw new IOException("file create failure...");
}

try {
BufferedWriter output = new BufferedWriter(new FileWriter(f));
output.write(contents);
output.close();
} catch (Exception e) {
throw new IOException(e);
}
}

static String formatLst(ArrayList <ClassObj> lst){
String contents = ""; //如何在这先循环第一行标题??
for(int i=0;i <lst.size();i++){
contents +=lst.get(i).getBand+"\t"+lst.get(i).getBuss+"\t"+lst.get(i).getPrice+"\t"+lst.get(i).getId+"\t"+lst.get(i).getLand+lst.get(i).getMan+"\t"+lst.get(i).getSum+"\n";
}
return contents;
}
}
class ClassObj {
private String Band;

private Double Buss;

private Double Price;

private String Id;

private String Land;

private String Man;

private Double Sum;

//get..set
public String toString() {
return "ClassObj{classBand=" + this.classBand +",classId="
+ this.classId + ",classGroup="
+ this.classGroup + ",classSum="
+ this.classSum + ",classNo=" + this.classNo +"}";
}
}


...全文
605 80 打赏 收藏 转发到动态 举报
写回复
用AI写文章
80 条回复
切换为时间正序
请发表友善的回复…
发表回复
crazylaa 2009-12-22
  • 打赏
  • 举报
回复
我的分分。。。。我得分的帖子里面居然没有这个帖子。。。。。
lsh902 2009-12-19
  • 打赏
  • 举报
回复
我想把jxl.jar放在JDK的安装目录里,让它想import java.*;那样直接就可以导入包,应该怎么设置啊??
另外我要是不建立工程,就只写一个*.java的文本,怎样才能正常导入jar包??
LLL710451618 2009-12-19
  • 打赏
  • 举报
回复
真好呢?
crazylaa 2009-12-19
  • 打赏
  • 举报
回复
[Quote=引用 76 楼 lsh902 的回复:]
我想把jxl.jar放在JDK的安装目录里,让它想import java.*;那样直接就可以导入包,应该怎么设置啊??
另外我要是不建立工程,就只写一个*.java的文本,怎样才能正常导入jar包??
[/Quote]

放jdk目录干吗?
如果你是web项目,就放在工程下得lib里面。如果你是cs项目,就应该自己建一个lib目录,然后在执行时classpath把这个lib里面得jar包都包含进来。
如果你就建一个java得文本,那你得到相应目录下去用javac编译,编译得时候指定classpath指向你的jar包位置。
你去看看java得编译过程,网上一堆。
lsh902 2009-12-19
  • 打赏
  • 举报
回复
顶起来!!!!
lsh902 2009-12-18
  • 打赏
  • 举报
回复
关于写入的代码,还有些问题要请教,现在有两种情况:
1.我用的是Microsoft SQL Server 2005在建表的时候,‘合计’这一项是要能实现select sum(合计)函数的所以这项的数据类型在没有小数点的情况下是numeric(18, 0),int(我只用过这两个类型)。有小数点的情况就只能用numeric(18, 1),所以我猜测批量写入的方法就不合适了,

pstmt.setString(1, c[0]);
pstmt.setString(2, c[1]);
pstmt.setInt(3,Integer.parseInt(c[2]));//如果这项是合计,没有小数的情况是否这样写??
//如果小数,可用setBigDecimal(new BigDecimal(c[2]));具体应该怎么写??这里没明白。

请问这种情况应当如何改进代码,没有小数的时候,SQL Server表中应该用那种数据类型??写入的代码
应该怎么改进??有小数点的话pstmt这应该怎么写?
crazylaa 2009-12-18
  • 打赏
  • 举报
回复
[Quote=引用 74 楼 lsh902 的回复:]
Java codewhile ((s= br.readLine())!=null) {if (s.indexOf("合计")>0) {continue;
}
String[] c= s.split("\t");
printArray(c);if (c.length==3) {//加入批量参数pstmt.setString(1, c[0]);
pstmt.setString(2, c[1]);
pstmt.setBigDecimal(new BigDecimal(c[2]));//是这个意思吗??pstmt.addBatch();
}
}
[/Quote]
lsh902 2009-12-18
  • 打赏
  • 举报
回复

while ((s = br.readLine()) != null) {
if (s.indexOf("合计") > 0) {
continue;
}
String[] c = s.split("\t");
printArray(c);
if (c.length == 3) {
//加入批量参数
pstmt.setString(1, c[0]);
pstmt.setString(2, c[1]);
setBigDecimal(new BigDecimal(c[2])); //是这个意思吗??
pstmt.addBatch();
}
}
crazylaa 2009-12-18
  • 打赏
  • 举报
回复
[Quote=引用 72 楼 lsh902 的回复:]
不好意思!是我失误了,没有小数点的批量是可以写的,SQL表用的numeric(18, 0)类型,pstmt.setInt(3,Integer.parseInt(c[2]));合计这样写可以写进去。
现在就是麻烦问一下,有小数点的具体怎么写???
//如果小数,可用setBigDecimal(new BigDecimal(c[2]));具体应该怎么写??这里没明白。

[/Quote]

如果你的字段类型定义为numeric(18, 1)
就用for循环里面不管是带不带小数点,都用setBigDecimal(new BigDecimal(c[2]))
lsh902 2009-12-18
  • 打赏
  • 举报
回复
不好意思!是我失误了,没有小数点的批量是可以写的,SQL表用的numeric(18, 0)类型,pstmt.setInt(3,Integer.parseInt(c[2]));合计这样写可以写进去。
现在就是麻烦问一下,有小数点的具体怎么写???
//如果小数,可用setBigDecimal(new BigDecimal(c[2]));具体应该怎么写??这里没明白。
crazylaa 2009-12-16
  • 打赏
  • 举报
回复
1.jxl.jar放在你工程的lib下,像你用到的jdbc驱动包等等,都放在你工程的lib下。如果不是ide,就要在-classpath里面把这些jar一个个写进去。
2.因为你的单价列长度不定(就是你的苹果香蕉个数不定,所以只能那么算,你要另外写个方法也可以,在classobj类内部写一个public count 方法,在设置了单价和数量之后再调用一下去计算总计栏,把总计设为classobj的一个属性,然后你的单价的那个Map做成一个静态类的静态成员变量在ClassObj里面可以直接用。
3.jxl应该能够追加,你可以先找到对应的已存在的excel文件的最大行数(jxl应该有相关方法来读excel的),然后写数据的时候从最大数据行的下一行开始写。jxl没用过,具体怎么弄你自己研究一下。
lsh902 2009-12-16
  • 打赏
  • 举报
回复
顶起来!!!!!
lsh902 2009-12-16
  • 打赏
  • 举报
回复
1.(比较弱的问题)我down了jxl.jar的包,我应该把包放到JDK的哪一个文件夹下??是不是还要在系统变量里设置classpath才能正常使用?(我之前只设了bin)
现在写import jxl.*;不管用,必须import jxl.WorkbookSettings; 。。。用哪个写哪个,而且文件还要写在src下面。否则就是:软件包 jxl 不存在。
2.代码的灵活性不强,要是向楼上那样要计算单价,合计的话,是不是要写单独的bean和contents??应当如何写??
3.像之前一样要让新数据跟在旧数据后面跑的话,就是true和flase的那个,我在jxl的doc里找了些类似的方法,但好像没成功,不知道是
方法没找对,还是没有if文件是否存在??求解。
我下的是这个jxl包:JExcelAPI的最新版本:jexcelapi_2_6_10.zip
下载地址:http://sourceforge.net/projects/jexcelapi/files/jexcelapi/2.6.10/jexcelapi_2_6_10.zip


class .....
{
public static void writeExcel(String efilePath)throws IOException{
String url = "jdbc:odbc:study11";
String user = "WSuser";
String password = "main@ws.com";
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = "select 业务量 as A,单价 as B,员工编号 as C from 表1";
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
con = DriverManager.getConnection(url,user,password);
pstmt = con.prepareStatement(sql);
rs = pstmt.executeQuery();

OutputStream outf = new FileOutputStream(efilePath);

WritableWorkbook wwb = Workbook.createWorkbook(outf);

WritableSheet ws = wwb.createSheet("sheettest", 0);
WritableFont font1 = new WritableFont(WritableFont.TIMES,16,WritableFont.BOLD,false,UnderlineStyle.DOUBLE);
WritableCellFormat format1=new WritableCellFormat(font1);
format1.setAlignment(jxl.format.Alignment.CENTRE);
format1.setBackground(Colour.PINK);
int i=0;
int j=0;
for (int k = 0; k < rs.getMetaData().getColumnCount(); k++) {
ws.addCell(new Label(k,0,rs.getMetaData().getColumnName(k+1),format1));
}
while(rs.next()){
System.out.println(rs.getMetaData().getColumnCount());
for (int k = 0; k < rs.getMetaData().getColumnCount(); k++) {
ws.addCell(new Label(k,j+i+1,rs.getString(k+1)));
}

i++;
}
wwb.write();
wwb.close();
} catch (Exception e) {
} finally {
try {
if (rs != null)
rs.close();
if (pstmt != null)
pstmt.close();
if (con != null)
con.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
try {
JExcelOperate.writeExcel("C:\\new_excel.xls");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
lsh902 2009-12-14
  • 打赏
  • 举报
回复
顶起来!!!
lsh902 2009-12-14
  • 打赏
  • 举报
回复
关于合计的问题还是没能解决,还是数据类型犯糊涂了。我把问题仔细的整理了一下,烦请高手帮忙解决!!
首先关于“单价”这一列,其实是下面的结构,
单价
苹果;桔子
桔子;香蕉;西瓜
香蕉;苹果
西瓜
桔子;西瓜

单价列其实是产品的名称,有多种产品的之间用“;”隔开,
在代码中用HashMap将名称替换为相应的人为规定的单价,然后在while循环中用split(";")拆分然后计算,
这一步没有问题,
现在要求合计的话,就要在formatLst里将单价(A)和业务量(B)相乘。单价肯定是Double型了,业务量
是count(*)出来的数据,应该用int型,但是运算的时候还是报错了。大家帮忙看看数据类型应当如何
转换,有没有更好的运算方法????


public static void main(String[] args)
{
.........
}
.........
String sql = "select 单价 as A,业务量 as B,员工编号 as C from 表1";
......
String fa = "";
ClassObj c1=null;
while(rs.next()){
fa = rs.getString("A");
c1=new ClassObj();
if(fa.indexOf(";") != -1){
double sum = 0;
String[] temp = fa.split(";");
for(int i = 0 ; i < temp.length; i ++){
sum += getPrice(temp[i]);
}
c1.setClassId(sum);
}else {
c1.setClassId(getPrice(fa));
}
c1.setClassGroup(rs.getString("B"));
c1.setClassNo(rs.getString("C"));
lst.add(c1);
}
。。。。。。
private static Map<String,Double> price = new HashMap<String,Double>(0);
static {
price.put("苹果", 1d);
price.put("桔子", 3d);
price.put("香蕉", 2.5);
price.put("西瓜", 1.6);
}
private static double getPrice(String name){
Double d = price.get(name);
return d == null ? 0 : d.doubleValue();
}
。。。。。。
static String formatLst(ArrayList<ClassObj> lst) {
String contents = "";
String total = "";
for (int i = 0; i < lst.size(); i++) {
Double hell=lst.get(i).getClassId();//从这开始就范糊涂了,
int song=lst.get(i).getClassGroup();
total = String.valueOf((hell).doubleValue*Integer.parseInt(song)); //???????帮忙解决
contents += lst.get(i).getClassId() +"\t"+lst.get(i).getClassGroup()
+"\t"+ lst.get(i).getClassNo() +"\n";
}
return contents;
}
crazylaa 2009-12-14
  • 打赏
  • 举报
回复
不用在formatLst里面去做,你取数据set到List里面的时候就可以做掉

while(rs.next()){
fa = rs.getString("A");
c1=new ClassObj();
double sum = 0; //提到前面来记录价格
if(fa.indexOf(";") != -1){

String[] temp = fa.split(";");
for(int i = 0 ; i < temp.length; i ++){
sum += getPrice(temp[i]);
}
c1.setClassId(sum);
}else {
sum = getPrice(fa); //只有一个,将价格记录下来
c1.setClassId(getPrice(fa));
}
int amount = 0;
try{
//取得数量并转为int
amount = Integer.parseInt(rs.getString("B"));
}catch(Exception e){
//如果有错,表示rs.getString("B")要么空,要么是无法转换的字符串,那么就不管,此时amount=0;
}
c1.setSong(sum*amount); //看你这里的情况来定,如果合计这个属性在ClassObj里面是double类型,那么就这样。如果是String,那就用 c1.setSong(String.valueOf(sum*amount));
c1.setClassGroup(rs.getString("B"));
c1.setClassNo(rs.getString("C"));
lst.add(c1);
}

下面那个犯糊涂的formatLst里面的计算可以去掉。
crazylaa 2009-12-08
  • 打赏
  • 举报
回复
lsh902

你加我QQ吧,有时候真替你急。。。
56525451
crazylaa 2009-12-08
  • 打赏
  • 举报
回复
[Quote=引用 59 楼 lsh902 的回复:]
引用 11 楼 crazylaa 的回复:
引用 9 楼 lsh902 的回复:
第一个问题的意思是,我开三个sql的目的是,分别在三组数据集中再跟着跑一个String类型的字段,例如:组长在SQL中是没有的,我先声明组长的名字String fa = "组长:张三";String fa = "组长:李四";String fa = "组长:王五";然后在while里分别跟着三张相应的表跑,
Java codewhile(rs.next()){//怎样将fa,跟相应的rs一起循环输出。          c1=new ClassObj();//c1.setBand(rs.getString("fa"));?????这儿应该有个for循环!              c1.setBuss(rs.getDouble("A"));
              c1.setPrice(rs.getDouble("B"));
              c1.setId(rs.getString("C"));//请问如何在遍历结果集时放到对象的sum字段中????能讲的详细点吗??//c1.setId(rs.getDouble(A*B));????              lst.add(c1);
          }

1.如果你每一行都要加上组长:张三的话,那你就在ClassObj里面再加个属性标识组长,然后在rs的每个while里面分别set进去。输出的时候再get出来。比如
Java codewhile(rs.next()){//怎样将fa,fb,fc跟相应的rs,rs2,rs3对应循环输出。              c1=new ClassObj();//c1.setBand(rs.getString("fa"));?????            c1.setCaptain("组长:张三");//第一个结果集的组长              c1.setBuss(rs.getDouble("A"));
              c1.setPrice(rs.getDouble("B"));
              c1.setId(rs.getString("C"));//怎么才能计算合并输出????//c1.setId(rs.getDouble(A*B));              lst.add(c1);
          }while(rs2.next()){
              c1=new ClassObj();
  c1.setCaptain("组长:李四");//第二个结果集的组长              c1.setBuss(rs.getDouble("D"));
              c1.setPrice(rs.getDouble("E"));
              c1.setId(rs.getString("F"));
              c1.setLand(rs.getString("G"));
              lst.add(c1);
          }while(rs3.next()){
              c1=new ClassObj();
c1.setCaptain("组长:王五");//第三个结果集的组长              c1.setBuss(rs.getDouble("H"));
              c1.setPrice(rs.getDouble("I"));
              c1.setId(rs.getString("J"));
              c1.setMan(rs.getString("K"));
              lst.add(c1);
          }



您误会我的意思了,您看分三个SQL写的目的是为了分别为三个结果集加入不同的“组长:XX”字段,像您写的这段代码是有问题的,while(rs.next())已经限制了循环的条件,所以c1.setCaptain("组长:张三")是跑不进来的(不知道是不是这个原因,但是这种写法是跑不起来的),最后我是开了三个 ArrayList <ClassObj>分别装三个SQL结果集,lst,lst2,lst3,然后返回了三个contents,才把三个组长加进去,
    static String formatLst(ArrayList <ClassObj> lst) {
        String contents = "";
        String Band ="组长:张三"  //应该有比这个更好的方法,不知道大家能不能想出更好的方法?
        for (int i = 0; i < lst.size(); i++) {
            contents += Band+"\t"+lst.get(i).getClassBuss() +"\t"+lst.get(i).getClassId() +"\t"。。。+"\n";
        }
        return contents;
    }

    static String formatLst2(ArrayList <ClassObj> lst2) {
        String contents2 = "";
        String Band ="组长:李四"
        for (int i = 0; i < lst2.size(); i++) {
            contents += Band+"\t"+lst2.get(i).getClassBuss() +"\t"+lst2.get(i).getClassId() +"\t"。。。+"\n";
        }
        return contents2;
    }
    static String formatLst3(ArrayList <ClassObj> lst3) {
        String contents3 = "";
        String Band ="组长:王五"
      。。。。。。
      代码重复的很多,但是需求还是满足了,因为三条SQL的组长是不同的,要是用union all装在一起的话,就不好判断分别加入组长了。

[/Quote]

呵呵,sql可以加的。不信你试:
select 业务量 as A,单价 as B,员工编号 as C,'组长:张三' as D from 表1;
看看查询结果,是不是D列所有的值都是'组长:张三'
在select语句中,你可以显式的把常量加进去作为查询结果的该列固定值。

你把band作为一个参数传进去,就不用写3个方法了。。。
static String formatLst(ArrayList <ClassObj> lst ,String band) {
String contents = "";
// String Band ="组长:张三" //应该有比这个更好的方法,不知道大家能不能想出更好的方法?
for (int i = 0; i < lst.size(); i++) {
contents += band+"\t"+lst.get(i).getClassBuss() +"\t"+lst.get(i).getClassId() +"\t"。。。+"\n";
}
return contents;
}
crazylaa 2009-12-08
  • 打赏
  • 举报
回复
[Quote=引用 60 楼 lsh902 的回复:]
关于写入数据库还有一个类似的问题,比如在SQL表中增加一个字段“导入数据日期”,txt文件中还是只有前四个字段,“导入数据日期”就是运行程序写入数据库的当前时间,应该怎么写?
String sql = "insert into tbl_report(单价,工号,统计量,日期,导入数据日期)" + "values(?,?,?,?,'nowDate()')";
[/Quote]

如果是日期型,就用 "values(?,?,?,?,getdate())"; 不要单引号
lsh902 2009-12-08
  • 打赏
  • 举报
回复
关于写入数据库还有一个类似的问题,比如在SQL表中增加一个字段“导入数据日期”,txt文件中还是只有前四个字段,“导入数据日期”就是运行程序写入数据库的当前时间,应该怎么写?
String sql = "insert into tbl_report(单价,工号,统计量,日期,导入数据日期)" + "values(?,?,?,?,'nowDate()')";
加载更多回复(60)

62,615

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧