MT2116: Addons to the CSV export

Add user-defined headers
Add CSV, field and subfield separator selection
This commit is contained in:
Matthias Meusburger 2010-01-15 17:42:43 +01:00 committed by Henri-Damien LAURENT
parent 85983247e4
commit 0865bd7727
6 changed files with 208 additions and 29 deletions

View File

@ -31,6 +31,7 @@ $VERSION = 3.00;
@EXPORT = qw(
&GetCsvProfiles
&GetCsvProfile
&GetCsvProfilesLoop
&GetMarcFieldsForCsv
);
@ -49,6 +50,18 @@ sub GetCsvProfiles {
}
# Returns all informations about a given csv profile
sub GetCsvProfile {
my ($id) = @_;
my $dbh = C4::Context->dbh;
my $query = "SELECT * FROM export_format WHERE export_format_id=?";
$sth = $dbh->prepare($query);
$sth->execute($id);
return ($sth->fetchrow_hashref);
}
# Returns fields to extract for the given csv profile
sub GetMarcFieldsForCsv {

View File

@ -341,6 +341,8 @@ C<$record> - a MARC::Record object
C<$csvprofileid> - the id of the CSV profile to use for the export (see export_format.export_format_id and the GetCsvProfiles function in C4::Csv)
C<$header> - true if the headers are to be printed (typically at first pass)
=back
=back
@ -351,36 +353,72 @@ C<$csvprofileid> - the id of the CSV profile to use for the export (see export_f
sub marc2csv {
my ($record, $id, $header) = @_;
my $output;
my $csv = Text::CSV->new();
# Get the information about the csv profile
my $marcfieldslist = GetMarcFieldsForCsv($id);
my $profile = GetCsvProfile($id);
# Getting separators
my $csvseparator = $profile->{csv_separator} || ',';
my $fieldseparator = $profile->{field_separator} || '#';
my $subfieldseparator = $profile->{subfield_separator} || '|';
# TODO: Be more generic (in case we have to handle other protected chars or more separators)
if ($csvseparator eq '\t') { $csvseparator = "\t" }
if ($fieldseparator eq '\t') { $fieldseparator = "\t" }
if ($subfieldseparator eq '\t') { $subfieldseparator = "\t" }
# Init CSV
my $csv = Text::CSV->new({ sep_char => $csvseparator });
# Getting the marcfields
my $marcfieldslist = $profile->{marcfields};
# Getting the marcfields as an array
my @marcfields = split('\|', $marcfieldslist);
my @marcfieldsarray = split('\|', $marcfieldslist);
# Separating the marcfields from the the user-supplied headers
my @marcfields;
foreach (@marcfieldsarray) {
my @result = split('=', $_);
if (scalar(@result) == 2) {
push @marcfields, { header => $result[0], field => $result[1] };
} else {
push @marcfields, { field => $result[0] }
}
}
# If we have to insert the headers
if ($header) {
my @marcfieldsheaders;
my $dbh = C4::Context->dbh;
# For each field or subfield
foreach (@marcfields) {
# We get the matching tag name
if (index($_, '$') > 0) {
my ($fieldtag, $subfieldtag) = split('\$', $_);
my $query = "SELECT liblibrarian FROM marc_subfield_structure WHERE tagfield=? AND tagsubfield=?";
my $sth = $dbh->prepare($query);
$sth->execute($fieldtag, $subfieldtag);
my @results = $sth->fetchrow_array();
push @marcfieldsheaders, @results[0];
my $field = $_->{field};
# If we have a user-supplied header, we use it
if (exists $_->{header}) {
push @marcfieldsheaders, $_->{header};
} else {
my $query = "SELECT liblibrarian FROM marc_tag_structure WHERE tagfield=?";
my $sth = $dbh->prepare($query);
$sth->execute($_);
my @results = $sth->fetchrow_array();
push @marcfieldsheaders, @results[0];
warn "else";
# If not, we get the matching tag name from koha
if (index($field, '$') > 0) {
my ($fieldtag, $subfieldtag) = split('\$', $field);
my $query = "SELECT liblibrarian FROM marc_subfield_structure WHERE tagfield=? AND tagsubfield=?";
my $sth = $dbh->prepare($query);
$sth->execute($fieldtag, $subfieldtag);
my @results = $sth->fetchrow_array();
warn "subfield $fieldtag, $subfieldtag";
push @marcfieldsheaders, $results[0];
} else {
my $query = "SELECT liblibrarian FROM marc_tag_structure WHERE tagfield=?";
my $sth = $dbh->prepare($query);
$sth->execute($field);
my @results = $sth->fetchrow_array();
warn "field $results[0]";
push @marcfieldsheaders, $results[0];
}
}
}
$csv->combine(@marcfieldsheaders);
@ -389,7 +427,8 @@ sub marc2csv {
# For each marcfield to export
my @fieldstab;
foreach my $marcfield (@marcfields) {
foreach (@marcfields) {
my $marcfield = $_->{field};
# If it is a subfield
if (index($marcfield, '$') > 0) {
my ($fieldtag, $subfieldtag) = split('\$', $marcfield);
@ -405,11 +444,11 @@ sub marc2csv {
push @tmpfields, $subfield;
}
}
push (@fieldstab, join(',', @tmpfields));
push (@fieldstab, join($subfieldseparator, @tmpfields));
# Or a field
} else {
my @fields = ($record->field($marcfield));
push (@fieldstab, join(',', map($_->as_string(), @fields)));
push (@fieldstab, join($fieldseparator, map($_->as_string(), @fields)));
}
};

View File

@ -2975,6 +2975,18 @@ if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) {
$DBversion = "3.01.00.101";
if (C4::Context->preference("Version") < TransformToNum($DBversion)) {
$dbh->do(qq{
ALTER TABLE `export_format` ADD `csv_separator` VARCHAR( 2 ) NOT NULL AFTER `marcfields` ,
ADD `field_separator` VARCHAR( 2 ) NOT NULL AFTER `csv_separator` ,
ADD `subfield_separator` VARCHAR( 2 ) NOT NULL AFTER `field_separator`
});
print "Upgrade done (added separators for csv export)\n";
SetVersion ($DBversion);
}
=item DropAllForeignKeys($table)
Drop all foreign keys of the table $table

View File

@ -49,8 +49,48 @@ function reloadPage(p) {
<label for="profile_description">Profile description :</label>
<textarea cols="50" name="profile_description" id="profile_description"></textarea><br /><br />
<label for="csv">CSV separator :</label>
<select name="csv_separator">
<option value=";">Colon (:)</option>
<option value="," selected="selected">Comma (,)</option>
<option value="|">Pipe (|)</option>
<option value=";">Semi-colon (;)</option>
<option value="#">Sharp (#)</option>
<option value=" ">Space ( )</option>
<option value="\t">Tabulation (\t)</option>
</select>
<br /><br />
<label for="field_separator">Field separator :</label>
<select name="field_separator">
<option value=";">Colon (:)</option>
<option value=",">Comma (,)</option>
<option value="|">Pipe (|)</option>
<option value=";">Semi-colon (;)</option>
<option value="#" selected="selected">Sharp (#)</option>
<option value=" ">Space ( )</option>
<option value="\t">Tabulation (\t)</option>
</select>
<br /><br />
<label for="subfield_separator">Subfield separator :</label>
<select name="subfield_separator">
<option value=";">Colon (:)</option>
<option value=",">Comma (,)</option>
<option value="|" selected="selected">Pipe (|)</option>
<option value=";">Semi-colon (;)</option>
<option value="#">Sharp (#)</option>
<option value=" ">Space ( )</option>
<option value="\t">Tabulation (\t)</option>
</select>
<br /><br />
<label for="profile_content">Profile marcfields :</label>
<textarea cols="50" name="profile_content" id="profile_content"></textarea>
<textarea cols="50" rows="2" name="profile_content" id="profile_content"></textarea>
<p>You have to define which fields or subfields you want to export, separated by pipes.<br />
You can also use your own headers (instead of the ones from koha) by prefixing the field number with an header, followed by the equal sign.<br />
Example&nbsp;: Personal name=200|Entry element=210$a|300
</p>
</fieldset>
<input type="hidden" name="action" value="create" />
<input type="submit" />
@ -59,7 +99,7 @@ function reloadPage(p) {
<!-- TMPL_IF NAME="existing_profiles" -->
<br /><br />
<h1>Modify or delete an existing profile</h1>
<h1 id="modify">Modify or delete an existing profile</h1>
<form action="/cgi-bin/koha/tools/csv-profiles.pl" method="post">
<fieldset class="brief">
@ -74,6 +114,44 @@ function reloadPage(p) {
<label for="modify_profile_description">Profile description :</label>
<textarea cols="50" name="profile_description" id="modify_profile_description"><!-- TMPL_VAR NAME="selected_profile_description" --></textarea><br /><br />
<label for="csv">CSV separator :</label>
<select name="csv_separator">
<option value=";">Colon (:)</option>
<option value=","<!-- TMPL_IF EXPR="selected_csv_separator eq ','" --> selected="selected"<!-- /TMPL_IF -->>Comma (,)</option>
<option value="|"<!-- TMPL_IF EXPR="selected_csv_separator eq '|'" --> selected="selected"<!-- /TMPL_IF -->>Pipe (|)</option>
<option value=";"<!-- TMPL_IF EXPR="selected_csv_separator eq ';'" --> selected="selected"<!-- /TMPL_IF -->>Semi-colon (;)</option>
<option value="#"<!-- TMPL_IF EXPR="selected_csv_separator eq '#'" --> selected="selected"<!-- /TMPL_IF -->>Sharp (#)</option>
<option value=" "<!-- TMPL_IF EXPR="selected_csv_separator eq ' '" --> selected="selected"<!-- /TMPL_IF -->>Space ( )</option>
<option value="\t"<!-- TMPL_IF EXPR="selected_csv_separator eq '\t'" --> selected="selected"<!-- /TMPL_IF -->>Tabulation (\t)</option>
</select>
<br /><br />
<label for="field_separator">Field separator :</label>
<select name="field_separator">
<option value=";">Colon (:)</option>
<option value=","<!-- TMPL_IF EXPR="selected_field_separator eq ','" --> selected="selected"<!-- /TMPL_IF -->>Comma (,)</option>
<option value="|"<!-- TMPL_IF EXPR="selected_field_separator eq '|'" --> selected="selected"<!-- /TMPL_IF -->>Pipe (|)</option>
<option value=";"<!-- TMPL_IF EXPR="selected_field_separator eq ';'" --> selected="selected"<!-- /TMPL_IF -->>Semi-colon (;)</option>
<option value="#"<!-- TMPL_IF EXPR="selected_field_separator eq '#'" --> selected="selected"<!-- /TMPL_IF -->>Sharp (#)</option>
<option value=" "<!-- TMPL_IF EXPR="selected_field_separator eq ' '" --> selected="selected"<!-- /TMPL_IF -->>Space ( )</option>
<option value="\t"<!-- TMPL_IF EXPR="selected_field_separator eq '\t'" --> selected="selected"<!-- /TMPL_IF -->>Tabulation (\t)</option>
</select>
<br /><br />
<label for="subfield_separator">Subfield separator :</label>
<select name="subfield_separator">
<option value=";">Colon (:)</option>
<option value=","<!-- TMPL_IF EXPR="selected_subfield_separator eq ','" --> selected="selected"<!-- /TMPL_IF -->>Comma (,)</option>
<option value="|"<!-- TMPL_IF EXPR="selected_subfield_separator eq '|'" --> selected="selected"<!-- /TMPL_IF -->>Pipe (|)</option>
<option value=";"<!-- TMPL_IF EXPR="selected_subfield_separator eq ';'" --> selected="selected"<!-- /TMPL_IF -->>Semi-colon (;)</option>
<option value="#"<!-- TMPL_IF EXPR="selected_subfield_separator eq '#'" --> selected="selected"<!-- /TMPL_IF -->>Sharp (#)</option>
<option value=" "<!-- TMPL_IF EXPR="selected_subfield_separator eq ' '" --> selected="selected"<!-- /TMPL_IF -->>Space ( )</option>
<option value="\t"<!-- TMPL_IF EXPR="selected_subfield_separator eq '\t'" --> selected="selected"<!-- /TMPL_IF -->>Tabulation (\t)</option>
</select>
<br /><br />
<label for="modify_profile_content">Profile marcfields :</label>
<textarea cols="50" name="profile_content" id="modify_profile_content"><!-- TMPL_VAR NAME="selected_profile_marcfields" --></textarea><br /><br />

30
test.pl Normal file
View File

@ -0,0 +1,30 @@
#!/usr/bin/perl
use strict;
use warnings;
my $string = $ARGV[0];
# Getting the marcfields as an array
my @marcfieldsarray = split('\|', $string);
# Separating the marcfields from the the user-supplied headers
my @marcfields;
foreach (@marcfieldsarray) {
my @result = split('=', $_);
if (scalar(@result) == 2) {
push @marcfields, { header => $result[0], field => $result[1] };
} else {
push @marcfields, { field => $result[0] }
}
}
use Data::Dumper;
print Dumper(@marcfields);
foreach (@marcfields) {
print $_->{field};
}

View File

@ -63,6 +63,9 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
my $profile_name = $input->param("profile_name");
my $profile_description = $input->param("profile_description");
my $profile_content = $input->param("profile_content");
my $csv_separator = $input->param("csv_separator");
my $field_separator = $input->param("field_separator");
my $subfield_separator = $input->param("subfield_separator");
my $action = $input->param("action");
my $delete = $input->param("delete");
my $id = $input->param("id");
@ -72,17 +75,17 @@ if ($profile_name && $profile_content && $action) {
my $rows;
if ($action eq "create") {
my $query = "INSERT INTO export_format(export_format_id, profile, description, marcfields) VALUES (NULL, ?, ?, ?)";
my $query = "INSERT INTO export_format(export_format_id, profile, description, marcfields, csv_separator, field_separator, subfield_separator) VALUES (NULL, ?, ?, ?, ?, ?, ?)";
my $sth = $dbh->prepare($query);
$rows = $sth->execute($profile_name, $profile_description, $profile_content);
$rows = $sth->execute($profile_name, $profile_description, $profile_content, $csv_separator, $field_separator, $subfield_separator);
}
if ($action eq "edit") {
my $query = "UPDATE export_format SET description=?, marcfields=? WHERE export_format_id=? LIMIT 1";
my $query = "UPDATE export_format SET description=?, marcfields=?, csv_separator=?, field_separator=?, subfield_separator=? WHERE export_format_id=? LIMIT 1";
my $sth = $dbh->prepare($query);
$rows = $sth->execute($profile_description, $profile_content, $profile_name);
$rows = $sth->execute($profile_description, $profile_content, $csv_separator, $field_separator, $subfield_separator, $profile_name);
warn "id $id";
}
if ($action eq "delete") {
@ -100,17 +103,21 @@ if ($profile_name && $profile_content && $action) {
# If a profile has been selected for modification
if ($id) {
my $query = "SELECT export_format_id, profile, description, marcfields FROM export_format WHERE export_format_id = ?";
my $query = "SELECT export_format_id, profile, description, marcfields, csv_separator, field_separator, subfield_separator FROM export_format WHERE export_format_id = ?";
my $sth;
$sth = $dbh->prepare($query);
$sth->execute($id);
my $selected_profile = $sth->fetchrow_arrayref();
warn "value : " . $selected_profile->[4];
$template->param(
selected_profile_id => $selected_profile->[0],
selected_profile_name => $selected_profile->[1],
selected_profile_description => $selected_profile->[2],
selected_profile_marcfields => $selected_profile->[3]
selected_profile_marcfields => $selected_profile->[3],
selected_csv_separator => $selected_profile->[4],
selected_field_separator => $selected_profile->[5],
selected_subfield_separator => $selected_profile->[6]
);
}