Script Report - Data return

This is more I think to do with Python than erpnext.

def execute(filters=None):
    if not filters: filters = {}

    float_precision = cint(frappe.db.get_default("float_precision")) or 3
    expiry = frappe.db.sql("""select distinct expiry_date from `tabBatch` order by expiry_date""", as_dict=1)
    iwb_map = get_item_warehouse_batch_map(filters, float_precision)
    columns = [_("Item") + ":Link/Item:100"]
    for e in expiry:
        columns += [str(e["expiry_date"])]
    data = []
    
        for i, item in enumerate(iwb_map):
        exp = []
       
        for e in expiry:
            inp =0
            for b in (iwb_map[item]):
                if e["expiry_date"] == b:
                    qty_dict = iwb_map[item][e.expiry_date]
                    exp.append(flt(qty_dict.bal_qty, float_precision))
                    inp = 1
            if inp == 0:exp.append(0)    
                         
        data.append([item, exp])
        

    return columns, data

The result is as follows. As you can see, instead of falling into the right column, It collects in one column.

as you are appending the list with only two values [item, exp], in slickgrid report it will only show 1st two column rest of the columns will be kept blank

You will need to prepare the list dynamically.
e.g.

data = [
    ["test item", "10.5.0", "", ""],
    ["test item", "", "0.0.6", ""]

data[i].append(flt(qty_dict.bal_qty, float_precision)) - this did the job, I am not sure why it didnt work earlier.