Отображение данных в файлы Excel - PullRequest
0 голосов
/ 23 марта 2012

У меня есть 635 текстовых файлов в одной папке. Я хочу прочитать эти данные в Excel. Это не такая простая задача, как кажется на первый взгляд. Я работал над экспортом файлов в Excel (с помощью stackoverflow :)) и теперь, когда у меня все получилось, я хочу закончить свое приложение. Вот параметры:

  1. В моей выходной электронной таблице Excel будет 637 столбцов, и данные будут вводиться начиная с третьего столбца. Как вы можете догадаться, каждый столбец (3-639) будет представлять одну из 635 подпапок.

  2. В электронной таблице 73902 строки, и данные будут записываться начиная с 3-й строки.

  3. Теперь записываемые данные поступают из 635 файлов. Каждый файл имеет 2 столбца. Например, чтобы заполнить столбец 5 (который будет соответствовать 5-2 = 3-й файл из 635 ) в листе Excel, перейдем к файлу 3rd и получим значения из там. Первый столбец в этом файле определяет, какие ячейки должны быть заполнены в листе Excel. Значения, которые необходимо заполнить, взяты из второго столбца этого файла (извините, если столбец слов запутался). Нам нужно заполнить 73900 строк для каждого столбца на листе (каждый столбец - 1 файл). А затем повторите это для 635 столбцов.

Если третий файл выглядит так:

5849 66883
395 4492863
681 1835871
817 4039961
835 3246671
868 4041156
889 1891481
1305 4467688
1317 175306
1361 3252611
2101 174589
4364 4053046
4897 4466547
4991 3879532
5327 3992891
5397 175328
6067 3881675
6075 176782
6906 2358727
7497 1838021

затем мы будем заполнять строки 5849, 385, 681,817 и так далее ... Мы заполняем эти ячейки соответствующими значениями из второго столбца в файле. Поэтому в 5-м столбце таблицы Excel ячейки 5849, 385, 681,817... будут заполнены значениями 66883,4492863,1835871,4039961...

Я прилагаю изображение листа Excel, чтобы прояснить ситуацию enter image description here

Пока у меня есть код Visual Basic для импорта текстовых файлов в Excel, но на самом деле я не обрабатываю информацию, рассмотренную выше. У меня также есть небольшой скрипт MATLAB, который делает то же самое (это не полностью функционирует) для записи данных в Excel. Я вставляю оба ниже.

Sub ReadFilesIntoActiveSheet()
Dim fso As FileSystemObject
Dim folder As folder
Dim file As file
Dim FileText As TextStream
Dim TextLine As String
Dim Items() As String
Dim i As Long
Dim cl As Range

' Get a FileSystem object
Set fso = New FileSystemObject

 ' get the directory you want
  Set folder = fso.GetFolder("D:\275_25bp")

' set the starting point to write the data to
 Set cl = ActiveSheet.Cells(1, 1)

' Loop thru all files in the folder
For Each file In folder.Files
' Open the file
Set FileText = file.OpenAsTextStream(ForReading)

' Read the file one line at a time
Do While Not FileText.AtEndOfStream
    TextLine = FileText.ReadLine

    ' Parse the line into | delimited pieces
    Items = Split(TextLine, " ")

    ' Put data on one row in active sheet
    For i = 0 To UBound(Items)
        cl.Offset(0, i).Value = Items(i)
    Next

    ' Move to next row
    Set cl = cl.Offset(1, 0)
Loop

' Clean up
FileText.Close
Next file

Set FileText = Nothing
Set file = Nothing
Set folder = Nothing
Set fso = Nothing

End Sub

####################### MATLAB SCRIPT ################### #############

dirname = uigetdir;#
Files = dir(fullfile(dirname,'*.txt'))
for i=1:numel(Files)
filename = fullfile(dirname,Files(k).name);
[col1,col2] = textread( filename, '%d%d' )
%pos1 = strcat('A',num2str(i));
%pos2 = strcat('B',num2str(i));
xlswrite('sample_output',col1,'Sheet1','A1:CI1')
xlswrite('sample_output',col2,'Sheet1','A2:CI2')
end

Нет общего шаблона именования для файлов-NAMES, за исключением того, что они являются уникальными именами. Папка содержит их в алфавитном порядке, поэтому файл 1 (начиная с A) и файл 635 (начнется с Z). Примеры имен файлов:

Acidothermus_cellulolyticus_11B-list.txt

Frankia_alni_ACN14a-list.txt ... Zymomonas_mobilis_ZM4-list.txt

Неважно, какой язык используется, но желательно что-то в UNIX (я знаю, что это не язык: P) или MATLAB (как я делал этот проект на этих двух языках).

Я очень признателен за помощь в этом. Пожалуйста, позвольте мне, если вам нужны какие-либо разъяснения о том, что необходимо сделать. Спасибо!

Ответы [ 2 ]

1 голос
/ 23 марта 2012

Я бы отделил проблему от "получения данных" и "размещения их в Excel". Кажется, вы знаете, как поместить данные в Excel, и это отлично, поэтому я остановлюсь на первом.

Самое замечательное, что у вас в основном большая таблица или матрица, а Matlab любит матрицы. Единственная проблема, которая может быть проблемой, это то, что ваша матрица очень большая, и, возможно, большая ее часть - нули. Все в порядке; мы можем использовать матрицу разреженную в Matlab.

data = sparse(nRowMax, nFiles);

Тогда алгоритм прост:

  1. Для каждого файла ...
    1. Определить номер столбца col.
    2. Для каждой строки ...
      1. Прочитать строку как row и value
      2. Вставить value в data(row, col)
    3. Повторяйте 2, пока все строки не будут прочитаны
  2. Повторяйте 1, пока все файлы не будут прочитаны.
  3. data теперь содержит все данные в том формате, который вам необходим в электронной таблице Excel. Экспортируйте его.

Код Matlab:

for col = 1:nFiles
    filename = files(k).filename;
    fileID = fopen(filename);
    filedata = textscan(fileID, "%d %d");

    rownumbers = filedata{1};
    values = filedata{2};

    for i = 1:length(rownumbers)
        row = rownumbers(i);
        value = values(i);
        data(row, col) = value;
    end
end
1 голос
/ 23 марта 2012

Поскольку вы можете использовать PERL, вот код / ​​скрипт PERL, который я сгенерировал для создания CSV-файла, который может быть загружен в Excel на основе приведенной выше информации. Все файлы должны быть в одном каталоге. Я синтаксис проверил это. Возможно, вам придется внести некоторые изменения в путь директории и имя файла в функции glob (например, имя с подстановочным знаком *). При вводе glob все файлы с расширением .dat будут найдены в локальном каталоге. Обязательно используйте обратную косую черту, если вы указали путь. Файлы будут обрабатываться в алфавитном порядке, так как функция сортировки выполняет афлобитную сортировку.

Если вы используете Window 7, вы можете взглянуть на ActiveState PERL. Таким образом, вам не нужно загружать и устанавливать Cygwin. Вы можете запустить его из командного окна. Это то, что я использовал для проверки синтаксиса сценария PERL, и у меня Windows 7, 64-битная.

* ПРИМЕЧАНИЕ. Обновлен код, приведенный ниже, для работы с cygwin PERL. Есть еще отладочные элементы, оставшиеся от усилий. *

use strict; 
#use File::Glob ':glob'; 

# Array to save the data 
my @savedData = (); 

# Get the files to process and sort them 
# NOTE: Edit for where the files exist if not 
# local directory from where script is run 
my @files = sort <*.txt>; 
print "number of files " . scalar(@files) . "\n"; # should be <*.txt> 
# Will shift columns on the output 
my $column = 0; 
# Save the numbers from the line 
my @numbers = (); 
my $lineNumber = 0; 

# Go through the files 
foreach my $f ( @files ) 
{ 
  # Open the file 
  #print "Processing file: $f\n"; 
  my %temp = (); 
  open INFILE,$f or die "Unable to open file: $f"; 

  # Read a line from the file 
  while ( <INFILE> ) 
  { 
    # Increment the line number, remove the carriage return 
    $lineNumber++; 
    chomp; 
    # Get the numbers from the line 
    @numbers = split("\\s+"); 
    # Check for error in amount of items 
    if ( 2 != scalar(@numbers)) 
    { 
      die "ERROR: Line not well formed in file: $f Line: $lineNumber\n"; 
    } 
    # Save the information using the first number as the row 
    $savedData[$numbers[0]][$column] = $numbers[1]; 
    $temp{$numbers[0]} = 1; 
    #print "$column $savedData[$numbers[0]][$column] "; 
    #print "@numbers\n"; 
  } 

  # Close the file and increment the column by 2 
  close(INFILE); 
  $column++; 
  my @keys = keys %temp; 
  @keys = sort { $a <=> $b} @keys; 
  #thisprint "Range of row indexes is: $keys[0] $keys[$#keys]\n "; # gives the range of rows 
} 

# Loop Control Variable 
my $lcv = 0; 
# Variable to save output 
my $output = ""; 
# Open output file 
# NOTE: File will be opened in current directory 
open OUTFILE,">output.csv" or die "Unable to open output file: output.csv"; 

# TO PRINT ROWS FROM 3RD POSTION 
#print OUTFILE ",,,\n,,,\n"; # can remove this 

#print "Scalar is " . scalar(@savedData) . "\n"; 
# For each row in the matrix 

# For each row in the matrix 
#for( $lcv = 1; $lcv < scalar(@savedData) ; $lcv++ ) 
#{ 
# construct the output for all of the columns 
# Two columns is to shift the output over by 2 columns 
#my $lcv2; 
#$output = ","; 
#print "items is: " . ref($savedData[$lcv]) . "\n"; 
#for($lcv2=0;$lcv2 < scalar(@files); $lcv2++) 
#{ 
#$output .= ",$savedData[$lcv][$lcv2]"; 
#} 
# write it to file 
#print OUTFILE "$output\n"; 
#} 

#close(OUTFILE); 

# For each row in the matrix 
for( $lcv = 1; $lcv < scalar(@savedData) ; $lcv++ ) 
{ 
  # construct the output for all of the columns 
  # Two columns is to shift the output over by 2 columns 
  my $lcv2; 
  $output = ","; 
  for($lcv2=0;$lcv2 < scalar(@files); $lcv2++) 
  { 
    $savedData[$lcv][$lcv2] = int($savedData[$lcv][$lcv2] + 0); 
    $output .= ",$savedData[$lcv][$lcv2]"; 
  } 
  # write it to file 
  print OUTFILE "$output\n"; 
} 

close(OUTFILE);

Перейдите к реализации карт вместо массивов, так как кажется, что программе не хватает памяти.

Вот измененный код.

use strict;  

# Map to save the data  
my %savedData = ();  

# Get the files to process and sort them  
# NOTE: Edit for where the files exist if not  
# local directory from where script is run  
my @files = sort <*.txt>;  
print "number of files " . scalar(@files) . "\n"; # should be <*.txt>  
# Will shift columns on the output  
my $column = 0;  
# Save the numbers from the line  
my @numbers = ();  
my $lineNumber = 0; 
my $lastRow = 0;
my $fileCount = 0;

# Go through the files  
foreach my $f ( @files )  
{  
  # Open the file 
  $fileCount++;  
  print "$fileCount: Processing file: $f\n";  
  my %temp = ();  
  open INFILE,$f or die "Unable to open file: $f";  

  # Read a line from the file  
  while ( <INFILE> )  
  {  
    # Increment the line number, remove the carriage return  
    $lineNumber++;  
    chomp;  
    # Get the numbers from the line  
    @numbers = split("\\s+");  
    # Check for error in amount of items  
    if ( 2 != scalar(@numbers))  
    {  
      die "ERROR: Line not well formed in file: $f Line: $lineNumber\n";  
    }  
    # Save the information using the first number as the row  
    $savedData{$numbers[0]}{$column} = $numbers[1];  
    $temp{$numbers[0]} = 1; 
    # Determine the last item in rows.  Save it for 
# future use
    if ( $lastRow < $numbers[0] )
    {
      $lastRow = $numbers[0];
    }

    #print "$column $savedData{$numbers[0]}{$column} ";  
    #print "@numbers\n";  
  }  

  # Close the file and increment the column by 2  
  close(INFILE);  
  $column++;  
  my @keys = keys %temp;  
  @keys = sort { $a <=> $b} @keys;  
  #thisprint "Range of row indexes is: $keys[0] $keys[$#keys]\n "; # gives the range of rows  
}  

# Loop Control Variable  
my $lcv = 0;  
# Variable to save output  
my $output = "";  
# Open output file  
# NOTE: File will be opened in current directory  
open OUTFILE,">output_map.csv" or 
   die "Unable to open output file: output_map.csv";  

# For each row in the matrix  
for( $lcv = 1; $lcv < $lastRow ; $lcv++ )  
{  
  # construct the output for all of the columns  
  # Two columns is to shift the output over by 2 columns  
  my $lcv2;  
  my $data = "";
  $output = ","; 
  for($lcv2=0;$lcv2 < scalar(@files); $lcv2++)  
  {  
    if ( exists $savedData{$lcv}{$lcv2} ) 
    {
      $data = int($savedData{$lcv}{$lcv2} + 0);  
      $output .= ",$data";  
    }
    else
    {
      $output .= ",0";
    }
  }  
  # write it to file  
  print OUTFILE "$output\n";  
}  

close(OUTFILE);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...