def excel_main(file):
    """
    Parse data from Excel spreadsheets into LiPD files.

    :param dict file: File metadata (source, name, etc)
    :return str dsn: Dataset name
    """

    os.chdir(file["dir"])
    name_ext = file["filename_ext"]

    # Filename without extension
    name = file["filename_no_ext"]
    # remove foreign characters to prevent wiki uploading errors
    name = normalize_name(name)
    print("processing: {}".format(name_ext))
    logger_excel.info("processing: {}".format(name_ext))

    pending_csv = []
    final = OrderedDict()
    logger_excel.info("variables initialized")

    # Create a temporary folder and set paths
    dir_tmp = create_tmp_dir()

    """
    EACH DATA TABLE WILL BE STRUCTURED LIKE THIS
    "paleo_chron": "paleo",
    "pc_idx": 1,
    "model_idx": "",
    "table_type": "measurement",
    "table_idx": 1,
    "name": sheet,
    "filename": sheet,
    "data": { column data }
    """

    # Open excel workbook with filename
    try:
        workbook = xlrd.open_workbook(name_ext)
        logger_excel.info("opened XLRD workbook")

    except Exception as e:
        # There was a problem opening a file with XLRD
        print("Failed to open Excel workbook: {}".format(name))
        workbook = None
        logger_excel.debug("excel: xlrd failed to open workbook: {}, {}".format(name, e))

    if workbook:

        # Build sheets, but don't make full filenames yet. Need to parse metadata sheet first to get datasetname.
        sheets, ct_paleo, ct_chron, metadata_str = _get_sheet_metadata(workbook, name)

        # METADATA WORKSHEETS
        # Parse Metadata sheet and add to output dictionary
        if metadata_str:
            logger_excel.info("parsing worksheet: {}".format(metadata_str))
            final = cells_dn_meta(workbook, metadata_str, 0, 0, final)

        # Now that we have the dataSetName, we can use it to build filenames
        dsn = __get_datasetname(final, name)
        filename = str(dsn) + ".lpd"
        sheets = __set_sheet_filenames(sheets, dsn)

        dir_bag = os.path.join(dir_tmp, "bag")
        dir_data = os.path.join(dir_bag, 'data')

        # Make folders in tmp
        os.mkdir(os.path.join(dir_bag))
        os.mkdir(os.path.join(dir_data))

        # PALEO AND CHRON SHEETS
        for sheet in sheets:
            logger_excel.info("parsing data worksheet: {}".format(sheet["new_name"]))
            sheet_meta, sheet_csv = _parse_sheet(workbook, sheet)
            if sheet_csv and sheet_meta:
                pending_csv.append(sheet_csv)
                sheet["data"] = sheet_meta

        # create the metadata skeleton where we will place the tables. dynamically add empty table blocks for data.
        skeleton_paleo, skeleton_chron = _create_skeleton_1(sheets)

        # Reorganize sheet metadata into LiPD structure
        d_paleo, d_chron = _place_tables_main(sheets, skeleton_paleo, skeleton_chron)

        # Add organized metadata into final dictionary
        final['paleoData'] = d_paleo
        final['chronData'] = d_chron

        # OUTPUT

        # Create new files and dump data in dir_data
        os.chdir(dir_data)

        # WRITE CSV
        _write_data_csv(pending_csv)

        # JSON-LD
        # Invoke DOI Resolver Class to update publisher data
        try:
            logger_excel.info("invoking doi resolver")
            final = DOIResolver(file["dir"], name, final).main()
        except Exception as e:
            print("Error: doi resolver failed: {}".format(name))
            logger_excel.debug("excel: doi resolver failed: {}, {}".format(name, e))

        # Dump final_dict to a json file.
        final["lipdVersion"] = 1.2
        final["createdBy"] = "excel"
        write_json_to_file(final)

        # Move files to bag root for re-bagging
        # dir : dir_data -> dir_bag
        logger_excel.info("start cleanup")
        dir_cleanup(dir_bag, dir_data)

        # Create a bag for the 3 files
        finish_bag(dir_bag)

        # dir: dir_tmp -> dir_root
        os.chdir(file["dir"])

        # Check if same lpd file exists. If so, delete so new one can be made
        if os.path.isfile(filename):
            os.remove(filename)

        # Zip dir_bag. Creates in dir_root directory
        logger_excel.info("re-zip and rename")
        zipper(root_dir=dir_tmp, name="bag", path_name_ext=os.path.join(file["dir"], filename))

    # Move back to dir_root for next loop.
    os.chdir(file["dir"])

    # Cleanup and remove tmp directory
    shutil.rmtree(dir_tmp)

    return dsn