Search code examples
javagroovygate

write the results of for loop to csv in groovy


currently I am using Groovy to create nested for loops that print the contents of objects to a string intended to be rows of delimited data. I would like to output these strings to a csv file however rather than printing them.

Here is the code:

for (doc in docs) {
    AnnotationSet row = doc.getAnnotations("Final").get("Row")
    AnnotationSet BondCounsel = doc.getAnnotations("Final").get("Bond_Counsel")
    AnnotationSet PurchasePrice = doc.getAnnotations("Final").get("PurchasePrice")
    AnnotationSet DiscountRate = doc.getAnnotations("Final").get("DiscountRate")
    for (b in BondCounsel) {
        for (d in DiscountRate) {
            for (r in row) {
                for (p in PurchasePrice) {
    println(doc.getFeatures().get("gate.SourceURL") + "|"
    + "mat_amount|" + r.getFeatures().get("MatAmount") + "|"
    + "orig_price|" + p.getFeatures().get("VAL") + "|"
    + "orig_yield|" + r.getFeatures().get("Yield") + "|"
    + "orig_discount_rate|" + d.getFeatures().get("rate")+ "|"
    + "CUSIP|" + r.getFeatures().get("CUSIPVAL1") + r.getFeatures().get("CUSIPVAL2") + r.getFeatures().get("CUSIPVAL3") + "|"
    + "Bond_Counsel|" + b.getFeatures().get("value"))
                }
            }
        }
    }
}

where the output are just a series of strings such as:

filename1|mat_amt|3|orig_price|$230,000.....
filename2|mat_amt|4|orig_price|$380,000.....

I understand I can set up a file writer i.e.

fileWriter = new FileWriter(fileName);
csvFilePrinter = new CSVPrinter(fileWriter, csvFileFormat);
csvFilePrinter.printRecord(FILE_HEADER);

<for loop here storing results>
csvFilePrinter.printRecord(forLoopResults)

But I am unsure how to properly format and store what I currently printing in the for loop to be able to pass onto csvFilePrinter.printRecord()

Any help would be great.


Solution

  • The printRecord() method takes an Iterable (per doc). e.g. a list.

    So in the inner loop of your code, rather than print, we would create a list for that row.

    Specifically, given this setup:

    def FILE_HEADER = ['Bond','Discount','Row','Price']    
    def fileName = 'out.csv'
    

    and this data aggregation (as an example):

    def BondCounsel = ['bc1','bc2']
    def DiscountRate = ['0.1','0.2']
    def row = ['r1','r2']
    def PurchasePrice = ['p1','p2']
    

    then this (edit: now made Groovier):

    new File(fileName).withWriter { fileWriter ->
        def csvFilePrinter = new CSVPrinter(fileWriter, CSVFormat.DEFAULT)
        csvFilePrinter.printRecord(FILE_HEADER)
    
        BondCounsel.each { b ->
            DiscountRate.each { d ->
                row.each { r ->
                    PurchasePrice.each { p ->
                        csvFilePrinter.printRecord([b, d, r, p])
                    }
                }
            }
        }
    }
    

    would generate this to out.csv:

    Bond,Discount,Row,Price
    bc1,0.1,r1,p1
    bc1,0.1,r1,p2
    bc1,0.1,r2,p1
    ... etc