|
|
|||||||||
|
|||||||||
| |||||||||
|
|
|
| |||||||||
![]() |
|
|
«
Previous Thread
|
Next Thread
»
|
Thread Tools | Search this Thread | Rate Thread | Display Modes |
|
|
|
Stop making mediocre tutorials.The best tutorials are video! Camtasia Studio makes it easy to create engaging, buzz-building screen videos at any size, in any popular format. Download the free trial!
|
|
#61
|
|||
|
|||
|
So if i did this: (added the database info at top and if I release the comment and define the exact number of columns that should do it?)
Code:
use strict;
use warnings;
use Data::Dumper;
use CGI qw/:standard *table/;
use CGI::Carp qw/fatalsToBrowser/;
use DBI;
$db="";
$host="";
$port="";
$userid="";
$passwd="";
$connectionInfo="DBI:mysql:database=$db;$host:$port";
my $dbh = DBI->connect($connectionInfo,$userid,$passwd)
or die("Cannot connect: $DBI::errstr\n");
print header, start_html, start_table;
my $file = 'parseMore.txt';
{
local $/ = "\r\n"; #not for you
open my $fh, "<", $file or die "Can't open $file: $!";
my $header = <$fh>;
chomp $header;
my @head = split /\t/, $header;
while (<$fh>) {
chomp;
my %row;
@row{@head} = split /\t/;
$row{'column3'} =~ s/"//g;
print start_table;
my @repeat = split /\n/, $row{'column3'};
foreach (@repeat) {
my @three = split /,/, $_, 2;
my @data = map {$row{$_} || undef} qw/column1 column2 column4 column5 column6 column7 column8 column9 column10/;
@data = (@data, @three);
print Tr(td(@data)) if $_ !~ /^\s*$/;
#$sth->execute(@data);
}
print end_table;
}
}
print end_html;
Last edited by electron_89 : April 24th, 2008 at 07:44 PM. |
|
#62
|
|||
|
|||
|
actually that causes problems. i added use DBI;
but still get compliation errors. |
|
#63
|
||||
|
||||
|
Code:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use CGI qw/:standard *table/;
use CGI::Carp qw/fatalsToBrowser/;
=pod
Print a standard html header.
If you want to use Data::Dumper to print data into the browswer,
then switch to text mode:
print header('text/text');
=cut
print header, start_html;
my $file = 'tsv_parse.tsv';
{
=pod
Tell perl to expect Windows line endings
Necessary because perl on the server is expecting Unix line endings
The special variable $/ is set to the OS line ending by default
If you override it, you need to do it with a local scope so you
don't ruin things for others.
That's why this section appears within the indented bracket;
it provides a scope for the $/
Outside of the blocks, the value will revert to the default automatically
=cut
local $/ = "\r\n";
# open the file
open my $fh, "<", $file or die "Can't open $file: $!";
=pod
The first line of your file is a header
I just grab it here to use as field definitions later.
You wouldn't want to insert this line anyway
=cut
my $header = <$fh>;
chomp $header;
# split the header row into individual names
my @head = split /\t/, $header;
while (<$fh>) {
=pod
Remove the line ending with chomp;
Because you changed $/ to Windows mode
the chomp command will remove \r\n from the line end
rather than just the normal \n it would have otherwise
That's not all $/ did for us though.
Without it, the <$fh> command would have stopped reading the line
in column3, when it came to a \n character
=cut
chomp;
=pod
Define a hash
Then use a hash slice to automatically fill it in
the keys to the hash will be the column names from the header row
and the values will be assigned to the correct positions
print Dumper \%row to see
=cut
my %row;
@row{@head} = split /\t/;
$row{'column3'} =~ s/"//g;
=pod
When inserting into a database, there will be no need to print to a table obviously
This is just for your enjoyment
=cut
print start_table;
=pod
We want to split column3 (if it's called column3
Otherwise change this name
=cut
my @repeat = split /\n/, $row{'column3'};
=pod
if there are no newlines, the split will move the only value it sees
into $repeat[0], so the array will still contain a single value
and the next section will proceed for a single interation
=cut
foreach (@repeat) {
=pod
The default variable $_ contains values like: VISHAY BC COMPONENTS, 2222036 Rule Based Upgrades
We will split them on space
One thing not tested here is that there are actually two values produced
Because of the limit, there will be no more than two, but it's possible you
could only have one
=cut
my @three = split /,/, $_, 2;
=pod
The row hash is not in a predictable order
You have to put the values in a set order for the insert
The map is an easy way. It will map out the columns in the order in which they are named.
Also, you only get the values you want. I skipped column3 because we will add it manually.
=cut
my @data = map {$row{$_} || undef} qw/column1 column2 column4 column5 column6 column7 column8 column9 column10/;
@data = (@data, @three); # combine the arrays. The split column three is added to the end
print Tr(td(@data)) if $_ !~ /^\s*$/;
#$sth->execute(@data); # insert it
}
print end_table;
}
}
print end_html;
You will have to show your code and the errors you receive. Last edited by keath : April 24th, 2008 at 08:11 PM. Reason: removed the #not for you comment, which keeps creeping back in |
|
#64
|
|||
|
|||
|
Keath, that is very clear...thx!
I still don't understand where I can indicate the database information and my db tablename etc... Can you show me in detail? ![]() |
|
#65
|
|||
|
|||
|
Some info: may be useful..
I have a total of 16 columns in my table in the db. one is the number count, the other at the end is the date when it was imported. |
|
#66
|
||||
|
||||
|
I don't have your database information. I created my own using postgres:
Code:
#!/usr/bin/perl -wT
use strict;
use CGI qw/:standard *table/;
use CGI::Carp qw/fatalsToBrowser/;
use DBI;
my $dbh = DBI->connect("dbi:Pg:dbname='test'", 'postgres', '', {'RaiseError'=>1}) or die "Unable to connect to db: $!";
$dbh->do('drop table some_stuff');
$dbh->do('create table some_stuff(column1 varchar(40),column2 varchar(40),column3 varchar(40),column4 varchar(40),column5 varchar(40),column6 varchar(40),column7 varchar(40),column8 varchar(40),column9 varchar(40),column10 varchar(40),columnU varchar(40))');
my $sth = $dbh->prepare('insert into some_stuff (column1, column2, column4, column5, column6, column7, column8, column9, column10, column3, columnU) values (?,?,?,?,?,?,?,?,?,?,?)');
print header, start_html;
my $file = 'tsv_parse.tsv';
{
local $/ = "\r\n";
open my $fh, "<", $file or die "Can't open $file: $!";
my $header = <$fh>;
chomp $header;
my @head = split /\t/, $header;
while (<$fh>) {
chomp;
my %row;
@row{@head} = split /\t/;
$row{'column3'} =~ s/"//g;
print start_table;
my @repeat = split /\n/, $row{'column3'};
foreach (@repeat) {
my @three = split /, /, $_, 2;
my @data = map {$row{$_} || undef} qw/column1 column2 column4 column5 column6 column7 column8 column9 column10/;
@data = (@data, @three);
if ($_ !~ /^\s*$/) {
print Tr(td(@data));
$sth->execute(@data);
}
}
print end_table;
}
}
print end_html;
and the insert worked: Code:
test=# select * from some_stuff; column1 | column2 | column3 | column4 | column5 | column6 | column7 | column8 | column9 | column10 | columnu ---------+---------+----------------------+---------+---------+---------+---------+---------+---------+----------+----------------------------- data1 | data2 | VISHAY BC COMPONENTS | data4 | data5 | data6 | data7 | data8 | data9 | data10 | 2222036 Rule Based Upgrades data1 | data2 | VISHAY BC COMPONENTS | data4 | data5 | data6 | data7 | data8 | data9 | data10 | 2222048 Rule Based Upgrades data1 | data2 | VISHAY BC COMPONENTS | data4 | data5 | data6 | data7 | data8 | data9 | data10 | 2222116 Rule Based Upgrades data1 | data2 | VISHAY BC COMPONENTS | data4 | data5 | data6 | data7 | data8 | data9 | data10 | 2222151 Rule Based Upgrades (4 rows) |
|
#67
|
|||
|
|||
|
wow that was fast. i am going to try it now but question...
my file has 16 columns but the output shows 12...i looked at the code but couldnt' figure out where i can set the amount of columns to parse. |
|
#68
|
||||
|
||||
|
You let perl parse the whole file. No need to try and limit it to certain columns.
When you are defining the data that you want to insert into the database, just name the columns you want: Code:
my @data = map {$row{$_} || undef} qw/column1 column2 column4 column5 column6 column7 column8 column9 column10/;
|
|
#69
|
|||
|
|||
|
Hmm... my original excel file had 16 columns.
so after reverting to tsv it should still retain 16 columns. when they were parsed, that should make 17 columns because we split the two from that one cell. when i run the script with the same tsv file, i see outputs and counted only 12 columns...so this is where i am confused. hey Keath thx for the database code part. it is very understandable...i am testing now... Quote:
|
|
#70
|
|||
|
|||
|
i had dumped the data successfully into the db =)
however, still problems with the other column data that is missing... i am looking at the code..trying to figure it out... |
|
#71
|
||||
|
||||
|
Yes, they are still there, but if you don't name them, they won't be moved by this code into the @data array.
Code:
my @data = map {$row{$_} || undef} qw/column1 column2 column4 column5 column6 column7 column8 column9 column10 column11 column12 column13 column14 column15 column16/;
This was by no means the only way. Here's another: Code:
foreach (@repeat) {
my @three = split /, /, $_, 2;
my @data = map {$row{$_} || undef} @head;
$data[2] = $three[0];
push @data, $three[1];
if ($_ !~ /^\s*$/) {
#print Tr(td(@data));
$sth->execute(@data);
}
}
Using @head to define the order ensures you will get every value; but you'll have to override the value of $data[2], because you don't want the original value there. You want the split. Then you have to decide where you want the extra bit. I pushed it to the end. |
|
#72
|
|||
|
|||
|
Keath!!! I got it! IT WORKS!!!!
You are not human! Owe you a huge one! |
|
#73
|
||||
|
||||
|
Cool. Since I'm not in L.A. to collect that meal, I'm headed to Wendy's. And for the blokes overseas, no that's not my girlfriend, unfortunately.
|
|
#74
|
|||
|
|||
|
Haha..Wendy's has excellent burgers. If you were here I would treat you to some Kobe Beef or Highest-End Sushi
You Rock! I'm Out! Love this forum...where can Donate? Quote:
|