beyond-the-cloud-dev / soql-lib

The SOQL Lib provides functional constructs for SOQL queries in Apex.
https://soql.beyondthecloud.dev/
MIT License
63 stars 10 forks source link

Idea for new feature. SOQL to CSV. #125

Open PawelWozniak opened 3 months ago

PawelWozniak commented 3 months ago

Hi. I am trying to create my implementation of SOQL to CSV and currently struggling with some issues like mixed field order or handling of parent and child relations.

Could you try to implement in your lib output conversion to CSV? Such a method should have a separator parameter as it is a comma or semicolon in different countries.

In my case business requirement is to make a report from surveys where we use text fields with 10000 characters in length. Bussines found that in such case field in report is truncated to 255 characters. According to SF documentation, this is expected behavior https://help.salesforce.com/s/articleView?id=000389623&type=1 . They want to have a report with full text field values.

My current implementation is below so you can understand what I am talking about.

    public static String queryToCSV (List<sObject> records, String delimiter) {
        String newLine = '\r\n';

        List<String> allCSVRows = new List<String>();
        Set<String> fieldNames = new Set<String>();
        List<Map<String, Object>> listOfRecords = new List<Map<String, Object>>(); // List of single records represented by Map<FieldAPIName, FieldValue>

        // Extract data from records list
        for (sObject record : records) {
            Map<String, Object> oneRecordFieldValuesMap = record.getPopulatedFieldsAsMap();
            listOfRecords.add(oneRecordFieldValuesMap);
            fieldNames.addAll(oneRecordFieldValuesMap.keySet());
        }

        List<String> tempRow = new List<String>();

        // Build CSV header
        for (String fieldName : fieldNames) {
            tempRow.add(fieldName.escapeCSV());
        }

        allCSVRows.add(String.join(tempRow, delimiter));

        // Add data rows
        for (Map<String, Object> valuesFromRecord : listOfRecords) {
            tempRow.clear();

            for (String fieldName : fieldNames) {
                Object value = valuesFromRecord.get(fieldName);

                if (value == null) {
                    value = '';
                }

                tempRow.add(('' + value).escapeCSV());
            }

            allCSVRows.add(String.join(tempRow, delimiter));
        }

        // Stick all rows together
        String finalCsv = String.join(allCSVRows, newLine);
        allCSVRows.clear(); // free heap

        return finalCsv;
    }