Re: Excel to MARC

[email protected] (Rich Ackerman)
Newsgroups perl.perl4lib
Message-ID <[email protected]>
Here's a program I wrote for our tech services department to make  
brief bibs from vendor spreadsheets.

Tech services get a spreadsheet from the vendor with information about  
newly ordered material. Each vendor obviously has a different data  
layout.

They copy the order spreadsheet into a new spreadsheet based on a  
template. They've created a template for each of their vendors. The  
first row has the desired MARC tags for the data in the column. The  
second row has default values. Third - nth row is vendor data.

Then they export the data to a tab delimited file and run this  
program. It makes MARC records that are loaded into III Millenium.

Feedback is welcome :)

Rich Ackerman
Nova Southeastern University
[email protected]


# perl script to create MARC records from a tab delimited textfile
# rich ackerman, april 25, 2007
#			
# Updates:	June 28, 2008 - generalize to new input data structure	
#		
##########################################################################
#
# This program makes MARC records from an input file, ready for
# uploading to NSU's Millenium system. If there are any problems
# with the data an error message is printed.
#
##########################################################################
#
# Input:	The input is a tab delimited file. There are three types
#			of input lines.
#
# 			1. The first line has MARC tag definitions for each column.
#			Every column must have a MARC tag definition.
#	
#			There are three different kinds of MARC tag definitions.
#
#			1a. Full Tag Definition - always six characters long.
#
#				A full tag defines a complete MARC tag with indicators and a  
subfield.
#				If you want to specify indicators do it in the first instance of  
the tag.
#
# 				Position	Value
#
#				1-3			Field Tag
#				4			First Indicator - space means "no indicator"
#				5			Second Indicator - space means "no indicator"
#				6			Subfield Code
#
# 				Examples: "1001 a", "260  b", "935  a", "24514a"
#
#			1b. Subfield Definition - always five characters long
#
#				A subfield definition defines a tag with no indicators OR adds a
#				subfield to an existing tag. The program will create the tag with
#				blank indicators if it is not already defined.
#
#				If the tag was defined in an earlier column, the subfield will be  
added.
#
#				Position	Value
#
#				1-3			Field Tag
#				4			Pipe (|)
#				5			Subfield code
#				
#				Examples: 960|a, 961|b
#
#			1c. Skip Column Definition - always three characters long
#
#				A tag 000 means skip the column. This will be used to void  
columns of
#				data that are not wanted in the MARC record.
#
# 			2. The second line specifies an optional default value for each  
MARC tag
#			in the first line.
#
# 			3. Lines 3-n contain data. The default value from the second line  
is used
#			if there is no value given.
#
##########################################################################
#
# Output: 	Two files containing MARC data. One is a compiled binary  
for loading into Millenium.
# 			The second is a text image for human inspection.
#
##########################################################################
#
# Calling sequence: p>perl bb.pl FILENAME [FILENAME2 ...]
#
##########################################################################

use MARC::Record;
use MARC::Field;
use strict;

my $i;			# count number of lines of input
my @marc;		# array to store MARC tags (line 1)
my @defaults;	# array to store default values (line 2)
my @data;		# array to store each input line (line 3 - n)

my $SKIPCOLUMN = '000';	# flag that says to ignore the whole column

# loop through multiple input files (even though we only expect one  
I'm lazy)

foreach (@ARGV) {

	# print "\nProcessing $_\n";

	$i = 0; # simple counter to count number of record processed
	
	my $inputfile  = $_;
	my ($name, $ext) = split (/\./, $inputfile);
	my $outputfile = $name . '.mrc';
	my $textdump = $name . '.mrc.txt';
	
	# open the input stream	
	open (INPUT, $inputfile) or die "Cannot open input file $inputfile:  
$!";
		
	# open the output streams
	open (OUTPUT, "> $outputfile") or die $!;
	open (TEXTDUMP, "> $textdump") or die $!;
	
	# read each line of the current input file and make a MARC record for  
it
	while ( <INPUT> ) {
		
		chomp($_); # get rid of line ending
		@data = split (/\t/);
		
		# First line? Save MARC tag definitions
		if ( $i == 0 ) {
			@marc = @data;
			print "Saving MARC definitions @marc\n";

		# Second line? Save default values
		} elsif ($i == 1) {
			@defaults = @data;
			print "Saving defaults @defaults\n";
		
		# Data line? Process it
		} else {
			
			# Feedback is a good thing
			print "Processing $data[0]\n";

			# create new record for this input line	
			my $record = MARC::Record->new();

			# Go through each column of data. Each column has a MARC tag
			# in @marc and a default value in @defaults. If the MARC tag
			# is the skip value then we just skip the column - information from
			# the vendor that we just don't need to bother with.
			 									
			for ( my $j = 0; $j < @marc; $j++ ) {
									
				next if $marc[$j] eq $SKIPCOLUMN;													
				
				# get the value we are going to set
				my $value = $data[$j] ? $data[$j] : $defaults[$j];
				
				# Now figure out what tag we are updating				
				my ($tag, $ind1, $ind2, $subfield) = '';								
				if ( length($marc[$j]) == 6 ) {

					# This is a full one, like 24514a or 156 3b
					$tag = substr($marc[$j], 0, 3);
					$ind1 = substr($marc[$j], 3, 1);
					$ind2 = substr($marc[$j], 4, 1);
					$subfield = substr($marc[$j], 5, 1);

				} elsif (length($marc[$j]) == 5 ) {
					
					# Just a subfield, like 960|a
					$tag = substr($marc[$j], 0, 3);
					$subfield = substr($marc[$j], 4, 1);

				} else {
					
					# This should never happen...
					my $errlen = length ( $marc[$j] ) ;
					print "Hey, this $marc[$j] is the wrong length: $errlen!\n";
					die;
				}
				
				my $field = $record->field($tag);
				
				# If the field exists and there is data to be stored in it,
				# then add another subfield.
				if ($field && $tag != 961) {									
					$field->add_subfields( $subfield => $value);				 					
					# print "Adding $value to $subfield\n";
				} else {				

				# Need to create a new field 				
					$field = MARC::Field->new (
						$tag, $ind1, $ind2,
						$subfield => $value);
					$record->append_fields($field);
				}
			}
					
			# Finally put the record in the output file
			print OUTPUT $record->as_usmarc();
			print TEXTDUMP $record->as_formatted();
			print TEXTDUMP "\n\n";
		}
		++$i; # bump line counter
	}
	close(OUTPUT);
	close(TEXTDUMP);
	
	$i = $i - 2; # don't count the line with the default settings on it  
or the MARC tags
	print "\n\nPut $i records into $outputfile and $textdump \n\n";
}






On Nov 13, 2008, at 12:40 AM, Saiful Amin wrote:

> On Wed, Nov 12, 2008 at 11:03 PM, Yan Liao  
> <[email protected]> wrote:
>
>> Does any one know how to trans data from Excel to MARC? There is a  
>> rush
>> local project and I don't have time to review my PERL class notes.
>>
>
> The best method would be to convert the Excel file into a delimited  
> text
> file (using 'Save As ..') and use MARC::Record to write the MARC  
> data by
> hand. There is a marvelous tutorial available for this module [1]  
> with lot
> of real examples. Once you get comfortable with this module you  
> probably
> won't look anywhere else for MARC related jobs in future.
>
> Having said that, I've just started working on a personal project of
> creating a web-based utility to enable conversion of Excel data into  
> MARC21.
> You can have look at the pre-alpha version in [2]. It is far from  
> complete,
> e.g., the download option in iso2709 or marcxml is yet to be  
> written. Any
> feedback would be welcome.
>
> [1]
> http://search.cpan.org/~mikery/MARC-Record-2.0.0/lib/MARC/Doc/Tutorial.pod
> [2] http://122.166.0.252/cgi-bin/xl2marc.pl
>
> -- 
> Saiful Amin
>
> Edutech India Pvt Ltd
> Bangalore, India.
> www.edutech.com
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.