5e8e0ed53c05f2ef9b51ce897440bae308367f47 chmalee Wed Feb 9 14:45:54 2022 -0800 Add csv output option to table browser to support opening files in Excel, refs #27623. Also change the output filename message to hint that Excel can auto-recognize .csv extensions and behave appropriately. Lastly, fix output dropdown selection to properly warn on update when using GTF output option or a snp table. diff --git src/hg/hgTables/bigBed.c src/hg/hgTables/bigBed.c index 202f0a9..70d433f 100644 --- src/hg/hgTables/bigBed.c +++ src/hg/hgTables/bigBed.c @@ -167,31 +167,31 @@ /* Get beds a region at a time. */ struct bed *bedList = NULL; struct region *region; for (region = regionList; region != NULL; region = region->next) addFilteredBedsOnRegion(bbi, region, table, filter, lm, &bedList); slReverse(&bedList); /* Clean up and return. */ if (retFieldCount != NULL) *retFieldCount = bbi->definedFieldCount; bbiFileClose(&bbi); freeMem(fileName); return bedList; } -void bigBedTabOut(char *db, char *table, struct sqlConnection *conn, char *fields, FILE *f) +void bigBedTabOut(char *db, char *table, struct sqlConnection *conn, char *fields, FILE *f, char outSep) /* Print out selected fields from Big Bed. If fields is NULL, then print out all fields. */ { if (f == NULL) f = stdout; /* Convert comma separated list of fields to array. */ int fieldCount = chopByChar(fields, ',', NULL, 0); char **fieldArray; AllocArray(fieldArray, fieldCount); chopByChar(fields, ',', fieldArray, fieldCount); /* Get list of all fields in big bed and turn it into a hash of column indexes keyed by * column name. */ struct hash *fieldHash = hashNew(0); struct slName *bb, *bbList = bigBedGetFields(table, conn); @@ -201,33 +201,41 @@ // If bigBed has name column, look up pasted/uploaded identifiers if any: struct hash *idHash = NULL; if (slCount(bbList) >= 4) idHash = identifierHash(db, table); /* Create an array of column indexes corresponding to the selected field list. */ int *columnArray; AllocArray(columnArray, fieldCount); for (i=0; i<fieldCount; ++i) { columnArray[i] = hashIntVal(fieldHash, fieldArray[i]); } /* Output row of labels */ -fprintf(f, "#%s", fieldArray[0]); +fprintf(f, "#"); +if (outSep == ',') fputc('"', f); +fprintf(f, "%s", fieldArray[0]); +if (outSep == ',') fputc('"', f); for (i=1; i<fieldCount; ++i) - fprintf(f, "\t%s", fieldArray[i]); + { + fputc(outSep, f); + if (outSep == ',') fputc('"', f); + fprintf(f, "%s", fieldArray[i]); + if (outSep == ',') fputc('"', f); + } fprintf(f, "\n"); /* Open up bigBed file. */ char *fileName = bigBedFileName(table, conn); struct bbiFile *bbi = bigBedFileOpenAlias(fileName, chromAliasChromToAliasHash(database)); struct asObject *as = bigBedAsOrDefault(bbi); struct asFilter *filter = NULL; if (anyFilter()) { filter = asFilterFromCart(cart, db, table, as); if (filter) { fprintf(f, "# Filtering on %d columns\n", slCount(filter->columnList)); } @@ -251,57 +259,71 @@ { names[ii] = nameList->name; nameList = nameList->next; } struct lm *lm = lmInit(0); struct bigBedInterval *ivList = bigBedMultiNameQuery(bbi, bpt, fieldIx, names, count, lm); char chromBuf[4096]; struct bigBedInterval *interval, *prevInterval = NULL; for (interval = ivList; interval != NULL; prevInterval = interval, interval = interval->next) { bigBedIntervalToRowLookupChrom(interval, prevInterval, bbi, chromBuf, sizeof chromBuf, startBuf, endBuf, row, bbi->fieldCount); if (asFilterOnRow(filter, row)) { int i; + if (outSep == ',') fputc('"', f); fprintf(f, "%s", row[columnArray[0]]); + if (outSep == ',') fputc('"', f); for (i=1; i<fieldCount; ++i) - fprintf(f, "\t%s", row[columnArray[i]]); + { + fputc(outSep, f); + if (outSep == ',') fputc('"', f); + fprintf(f, "%s", row[columnArray[i]]); + if (outSep == ',') fputc('"', f); + } fprintf(f, "\n"); } } } else { /* Loop through outputting each region */ struct region *region, *regionList = getRegions(); for (region = regionList; region != NULL; region = region->next) { struct lm *lm = lmInit(0); struct bigBedInterval *iv, *ivList = bigBedIntervalQuery(bbi, region->chrom, region->start, region->end, 0, lm); for (iv = ivList; iv != NULL; iv = iv->next) { bigBedIntervalToRow(iv, region->chrom, startBuf, endBuf, row, bbi->fieldCount); if (asFilterOnRow(filter, row)) { if ((idHash != NULL) && (hashLookup(idHash, row[3]) == NULL)) continue; int i; + if (outSep == ',') fputc('"', f); fprintf(f, "%s", row[columnArray[0]]); + if (outSep == ',') fputc('"', f); for (i=1; i<fieldCount; ++i) - fprintf(f, "\t%s", row[columnArray[i]]); + { + fputc(outSep, f); + if (outSep == ',') fputc('"', f); + fprintf(f, "%s", row[columnArray[i]]); + if (outSep == ',') fputc('"', f); + } fprintf(f, "\n"); } } lmCleanup(&lm); } } /* Clean up and exit. */ bbiFileClose(&bbi); hashFree(&fieldHash); freeMem(fieldArray); freeMem(columnArray); } static unsigned slCountAtMost(const void *list, unsigned max)