daveinOK2004
MIS
I don't really know how to title this message, so hope that worked 
I'm working on a program that parses and modifies a CSV file. The source file is an export of another companies address book. I make the necessary alterations to make it importable into our Active Directory as mail enabled contacts. There are roughly 4500 lines in the source CSV
file. My script works perfectly on it.
However, if I use Excel and sort the file by last name prior to running my script, then the script barfs repeatedly with this error:
Use of uninitialized value in pattern match (m//) at blib\lib\Text\CSV.pm (autosplit
into blib\lib\auto\Text\CSV\combine.al) line 139, <CSV_IN> line 4433.
Use of uninitialized value in substitution (s///) at blib\lib\Text\CSV.pm (autosplit
into blib\lib\auto\Text\CSV\combine.al) line 154, <CSV_IN> line 4433.
Use of uninitialized value in concatenation (.) or string at blib\lib\Text\CSV.pm
(autosplit into blib\lib\auto\Text\CSV\combine.al) line 156, <CSV_IN> line 443
3.
The data is exactly the same, it's just the order in the CSV file that is different. Any ideas why or how to fix?
Here's my code:
I'm working on a program that parses and modifies a CSV file. The source file is an export of another companies address book. I make the necessary alterations to make it importable into our Active Directory as mail enabled contacts. There are roughly 4500 lines in the source CSV
file. My script works perfectly on it.
However, if I use Excel and sort the file by last name prior to running my script, then the script barfs repeatedly with this error:
Use of uninitialized value in pattern match (m//) at blib\lib\Text\CSV.pm (autosplit
into blib\lib\auto\Text\CSV\combine.al) line 139, <CSV_IN> line 4433.
Use of uninitialized value in substitution (s///) at blib\lib\Text\CSV.pm (autosplit
into blib\lib\auto\Text\CSV\combine.al) line 154, <CSV_IN> line 4433.
Use of uninitialized value in concatenation (.) or string at blib\lib\Text\CSV.pm
(autosplit into blib\lib\auto\Text\CSV\combine.al) line 156, <CSV_IN> line 443
3.
The data is exactly the same, it's just the order in the CSV file that is different. Any ideas why or how to fix?
Here's my code:
Code:
#!/usr/bin/perl -w
use strict;
use warnings;
use Text::CSV;
##############################################
# CSV prep utility v1.1 #
# by David Burklin 6/26/07 #
# #
# This utility will take a CSV file export #
# and prepare it for input into our Exchange #
# 2003 Server as a mail enabled contact. #
##############################################
# Source CSV file will look like this:
# HEADER: Obj-Dist-Name (DN),Display Name (cn),E-Mail Addresses (rfc822Mailbox),Company (Company),
# Department (department), Office (physicalDeliveryOfficeName),Phone Number (telephoneNumber),
# First Name (givenName),Initials (initials),Last Name (sn),Title (title)
# RECORD: /o=DOMAIN/ou=LOCATION/cn=Recipients/cn=BobMarley,"Marley, Bob",bobm@rasta.org,Rasta Inc,
# Voice Services,"Kingston, Jamaica", 777-555-1234,Bob,B,Marley,rastafarian
# Define the files that will be used. Future revision may prompt for these with the values here as a default.
my $infile = 'c:\work\input.csv';
my $outfile = 'c:\work\output.csv';
# Other data used.
my @skipcn = ('EAdmin','IAdmin','NAdmin','Administrator','NetappAutosupport','BESADMIN','NWTRfictest1',
'NWTRPGP','bosc-cmsupport','EBTC','ABCT2', 'DSecurity','DSTUpdate','EOffice','thou',
'ABoston','EBoston','TBoston','SMail','MMailbox','qmailbox','SMailbox','WAnthony',
'TSMailbox','masterp','MPlace', 'TNetwork-Unity','EOKC','PFRepl','PGPValidate','SecAlert',
'SConsole','Sreports','SQLServerAccount','BSQL','SQLMAILTEST','SReport','ISynergy','TCop',
'TOperator','tmain','TSQLMail','ExchangeT','ExchangeUser','W2','IWebmaster','JWright-Test');
my $skip=0;
my $RecCnt=0; #count records processed.
my $RecWrt=1; #start at 1 for the header.
my $lastcn=""; #will be used to handle dupe CN entries.
my $lastcnfx=1; #used in conjunction with $lastcn
# Create CSV instances for input and output using the TEXT::CSV module
my $csv = Text::CSV->new();
my $csvout = Text::CSV->new();
# Open the infile and create the outfile.
open (CSV_IN, "<", $infile) or die $!;
open (CSV_OUT, ">", $outfile) or die $!;
# Create an array with the fieldnames. Write this as the header for the output CSV file.
my @fields = ('DN','objectClass','cn','distinguishedName','instanceType','displayName','targetAddress',
'mailNickname','name','objectCategory','mail','sn','givenName','showInAddressBook',
'Company','Department','physicalDeliveryOfficeName','telephoneNumber','title');
if ($csv->combine (@fields)) {
my $string = $csv->string;
print CSV_OUT "$string\n";
}
else {
my $err = $csv->error_input;
print "combine () failed on argument: ", $err, "\n";
}
# Begin parsing through the source file. Store the fields in variables denoted by the inFieldName.
my $dump_header=0;
while (<CSV_IN>) {
$RecCnt = $RecCnt + 1;
if ($dump_header<1) {$dump_header=1;} else
{
if ($csv->parse($_)) {
my @columns = $csv->fields();
my $inDN = $columns[0];
my $inCN = $columns[1];
my $inrfc822Mailbox = $columns[2];
my $inCompany = $columns[3];
my $inDepartment = $columns[4];
my $inphysicalDeliveryOfficeName = $columns[5];
my $intelephoneNumber = $columns[6];
my $ingivenName = $columns[7];
my $inInitials = $columns[8];
my $insn = $columns[9];
my $intitle = $columns[10];
#Now that we have the input fields, prepare the data for our output file.
# break the incoming DN down to get just the CN from it.
my @ary=split('/',$inDN);
my $cntmp=$ary[-1];
@ary=split('=',$cntmp);
my $cn = $ary[-1];
#This routine will ensure that every CN is unique by appending a numeric
#value to the end of any that are dupes.
#if (lc($cn) eq lc($lastcn))
# {
# $cn=$cn . sprintf("%u",$lastcnfx);
# }
#$lastcn=$cn;
#now create the fields for output.
my $DN="CN=$cn,OU=NWTR,DC=domain,DC=local";
if ($RecCnt/10==int($RecCnt/10)){print ".";} # gives a visual progress indicator.
my $objectClass = "contact";
my $distinguishedName = "OU=NWTR,DC=domain,DC=local";
my $instanceType = "4";
my $displayName = "$ingivenName $inInitials $insn";
my $targetAddress = "SMTP:$inrfc822Mailbox";
my $mailNickname = "$ingivenName$insn$inInitials";
my $name = $displayName;
my $objectCategory = "CN=Person,CN=Schema,CN=Configuration,DC=domain,DC=local";
my $mail = $inrfc822Mailbox;
my $sn = $insn;
my $givenName = $ingivenName;
my $showInAddressBook = "CN=Default Global Address List,CN=All Global Address Lists,
CN=Address Lists Container,CN=Exchange Organization,CN=Microsoft Exchange,CN=Services,
CN=Configuration,DC=domain,DC=local;CN=All Contacts,CN=All Address Lists,
CN=Address Lists Container,CN=Exchange Organization,CN=Microsoft Exchange,CN=Services,
CN=Configuration,DC=domain,DC=local";
my $Company = $inCompany;
my $Department = $inDepartment;
my $physicalDeliveryOfficeName = $inphysicalDeliveryOfficeName;
my $telephoneNumber = $intelephoneNumber;
my $title = $intitle;
# Now create an array containing the output data.
my @fields = ($DN,$objectClass,$cn,$distinguishedName,$instanceType,$displayName,
$targetAddress,$mailNickname,$name,$objectCategory,$mail,$sn,$givenName,
$showInAddressBook,$Company,$Department,$physicalDeliveryOfficeName,
$telephoneNumber,$title);
# Now we are going to compare against the array skipcn. If the cn is on the skip list then
#bypass it. Otherwise, write it to the output file.
foreach my $comparecn (@skipcn)
{
if (lc($comparecn) eq lc($cn))
{
print "\nSkipping:$comparecn";
$skip=1;
}
}
if ($skip==0)
{
#write it to the output file
if ($csv->combine (@fields))
{
my $string = $csv->string;
print CSV_OUT "$string\n";
$RecWrt=$RecWrt+1;
}else
{
my $err = $csv->error_input;
print "combine () failed on argument: ", $err, "\n";
}
}else{$skip=0;}
} else {
my $err = $csv->error_input;
print "\nFailed to parse line: $err\n";
}
}#end dump header
}
# close open handles and you are done.
close CSV_OUT;
close CSV_IN;
print "\n\n$RecCnt records processed from $infile.";
print "\n$RecWrt records written to $outfile.\n";
### The resultant file can now be imported to Active Directory using
### csvde -i -f c:\work\output.csv -v -j c:\log
### from the exchange system console.