Чтение Excel-файлов средствами PHP

Если вам необходимо читать файлы Excel (.xls) средствами PHP, то библиотека PHP-ExcelReader создана специально для вас. Для работы необходима поддержка iconv или mbstring. Вот пример того, как можно оформить вывод xls-документа в HTML-таблицу с использованием этой библиотеки:

<?php
require_once ('Excel/reader.php');

$data = new Spreadsheet_Excel_Reader();
$data->setOutputEncoding('CP1251');
$data->read('filename.xls');     

echo '<table>';
for ($i = 1; $i <= $data->sheets[0]['numRows']; $i++) {
  echo '<tr>';
  for ($j = 1; $j <= $data->sheets[0]['numCols']; $j++) {
    echo '<td>'.$data->sheets[0]['cells'][$i][$j].'</td>';
  }
  echo '</tr>';
}
echo '</table>';
?>

Альтернативный вариант - PHP Excel PARSER. Вот что написано в файле Help_rus.txt:

Вам нужен скрипт, который может читать MS файлы Excel и сохранять данные в базе данных, HTML страницах и и т.д.? Вы хотите делать это используя PHP под Unix и Linux, но без того, чтобы использовать инструментальные средства Windows напоподобии COM? Тогда PHP Excel PARSER - для вас. Все, в чем вы будете нуждаться - это только наш excel.php и PHP сервер без установки дополнительных инструментальных средств.

В файле документации Help_rus.txt довольно подробно описано, как использовать PHP Excel PARSER. Кроме того, дистрибутив содержит примеры работы с Excel-файлом:

  • PHP Excel Parser/Setup/SAMPLE/XLS2HTML/SAMPLE.PHP - вывод Excel-файла в браузер
  • PHP Excel Parser/Setup/SAMPLE/xls2mysql/INDEX.PHP - запись Excel-файла в базу данных

Пример вывода Excel-файла в браузер в формате HTML:

<?php
include ("excel.php");

$exc = new ExcelFileParser ("log.txt", ABC_NO_LOG);
$res = $exc->ParseFromFile("test.xls");

switch ($res) {
    case 0: break;
    case 1: die ("Невозможно открыть файл");
    case 2: die ("Файл, слишком маленький чтобы быть файлом Excel");
    case 3: die ("Ошибка чтения заголовка файла");
    case 4: die ("Ошибка чтения файла");
    case 5: die ("Это - не файл Excel или файл, сохраненный в Excel < 5.0");
    case 6: die ("Битый файл");
    case 7: die ("В файле не найдены данные  Excel");
    case 8: die ("Неподдерживаемая версия файла");
    default: die ("Неизвестная ошибка");
}

// цикл по рабочим листам
for( $ws_num=0; $ws_num<count($exc->worksheet['name']); $ws_num++ )
{                 
    echo "<h3>Рабочий лист: ";
    if( $exc->worksheet['unicode'][$ws_num] )
        echo uc2cp1251($exc->worksheet['name'][$ws_num]);
    else
        echo $exc->worksheet['name'][$ws_num];

    echo "</h3>\n";
    $ws = $exc->worksheet['data'][$ws_num];

    // если рабочий лист не пустой
    if ( is_array($ws) && isset($ws['max_row']) && isset($ws['max_col']) ) {
        echo "<table border=1 cellspacing=0 cellpadding=2>\n";

        echo "<tr><td>&nbsp;</td>";
        for( $j=0; $j<=$ws['max_col']; $j++ ) {
            echo "<td class=index>&nbsp;";
            if( $j>25 ) echo chr((int)($j/26)+64);
            echo chr(($j % 26) + 65)."&nbsp;</td>";
        }
        echo "</tr>\n";
        // начало цикла по строкам
        for( $i=0; $i<=$ws['max_row']; $i++ ) {
            echo "<tr><td class=index>".($i+1)."</td>\n";
            // начало цикла по столбцам
            if( isset($ws['cell'][$i]) && is_array($ws['cell'][$i]) ) {
                for( $j=0; $j<=$ws['max_col']; $j++ )
                {
                    if( isset($ws['cell'][$i][$j]) ) {

                        // Печать данных ячейки
                        echo "<td>";
                        $data = $ws['cell'][$i][$j];
                       
                        switch ($data['type'])
                        {
                            // строка
                            case 0:
                                $ind = $data['data'];
                                if( $exc->sst['unicode'][$ind] )
                                    $s = uc2cp1251($exc->sst['data'][$ind]);
                                else
                                    $s = $exc->sst['data'][$ind];
                                if( strlen(trim($s))==0 )
                                    echo "&nbsp;";
                                else
                                    echo $s;
                                break;
                            //целое число
                            case 1:
                                echo (int)($data['data']);
                                break;
                            //вещественное число
                            case 2:
                                echo (float)($data['data']);
                                break;
                            // дата
                            case 3:
                                $ret = $exc->getDateArray($data['data']);
                                printf ("%s-%s-%s",$ret['day'], $ret['month'], $ret['year']);
                                break;
                            default:
                                echo "&nbsp;";
                                break;
                        }
                        echo "</td>\n";
                           
                    } else {
                        echo "<td>&nbsp;</td>\n";
                    }
                }
            } else {
                // все ячейки стрки пустые
                for( $j=0; $j<=$ws['max_col']; $j++ ) {
                    echo "<td>&nbsp;</td>\n";
                }
            }
            echo "</tr>\n";
           
        }

        echo "</table>\n";
    } else {
        // пустой рабочий лист
        echo "<p>Пустой рабочий лист</p>\n";
    }
} 

// конвертим в нужную кодировку
function uc2cp1251($str) {
    return iconv('UNICODELITTLE','cp1251',$str);
}
?>

Ссылки по теме:

Ликбез по сетевым технологиям

DHCP

Вы проснулись после дикой пьянки. Первые ваши слова “кто я?” и “где я?”. Сосед, который не запивал водку пивом, вам сообщает все ваши параметры: кто вы и где. Этот сосед выступает в роли DHCP-сервера. Учтите, что в сети могут быть так называемые “ложные DHCP-сервера”, например жена: на ваш вопроc “кто я?” она выдаст неверную информацию — “алкоголик ты проклятый”. Так что не всегда динамическая выдача параметров безопасна, рекомендуется записывать свои параметры (как зовут, ваш адрес и т.д.) на бумажке.

Маршрут по умолчанию

Подойтите к прохожему и спросите “не подскажите ли вы как пройти к моргу имени Невмировича-Данченко?”. С большой долей вероятности вас пошлют. Так вот это и есть маршрут по умолчанию, другими словами если адрес назначения не известен, то пакеты посылаются на маршрут по умолчанию (синонимы: шлюз по умолчанию, default gateway).

Понятие TTL

Представьте себе, что вам 5 лет и вы хотите кушать. Вы идете к папе и говорите: “Папа, я хочу кушать”. Ваш папа смотрит телевизор, согласно таблице маршрутизации он посылает вас к маме. Вы идете к ней и просите “Мамааа, я хочу кушать”. Мама болтает с подругой по телефону и согласно своей таблице маршрутизации посылает вас к папе. И так вы ходите как дурак от папы к маме и обратно, туда-сюда, туда-сюда, а все потому что криворукие админы (родители папы и мамы) неправильно настроили таблицу маршрутизации. Чтобы защититься от таких ситуаций придумали понятие TTL (Time To Live), что применительно к нашей ситуации означает количество терпения у мальчика, пока он не скажет “заколебало” и не упадет перед ногами мамы или папы в беспомощном состоянии. Последний, по правилам (стандарты - это “так заведено в семье”), обязан послать короткий нелестный отзыв в адрес того, кто послал мальчика кушать. Это так называемый icmp-пакет “мальчик издох”.

Ping

Вы конечно бывали в ситуации “сам дурак”. Вы кричите “Петя ты, дурак”, а в ответ слышите “Вася, сам дурак”. Это простеший пинг. Вы только что пропинговали Петю. Не все отвечают на пинги, особо культурные, например Microsoft.com не утруждают себя реагированием на ваши запросы. С такими переругиваться бесполезно, мы знаем, что они слышат и злятся, но реакции добиться не можем. Тем не менее, пинг - неплохой способ узнать жив ли хост, ведь пиная труп ногами не добьешься реакции “сам дурак”.

Traceroute

Представь себе, что ты живешь на 9-м этаже и хочешь узнать всех жильцов которые живут от тебя до Клавки с 3-го. Ты берешь взрывпакет и, исходя из формулы свободного падения, рассчитываешь время взрыва пакета над 8-м этажом. Это TTL=1. После того как пакет взорвется - выглянет озверевшая рожа соседа с 8-го этажа. Время реакции зависит от загруженности сервера, т.е. от занятости соседа и от шейпов, т.е. в воздухе ли ваша система или ты живешь на планете, где атмосфера жидкий азот. Так вот, если вообще не дождешься ответа - твой сосед глухой - у него запрещены icmp ответы, либо он запретил их только для тебя если его уже заколебали твои финты и он научился тебя игнорировать. Дальше выставляешь TTL=2 и т.д. Не забывай, что если Клавка живет выше тебя - это No route to host.

Работа с архивами средствами PHP

На http://www.phpclasses.org можно скачать класс Create ZIP File, предназначенный для создания zip-файлов с иерархией папок. Пример использования:

<?php
// Подключаем класс для работы с zip-архивами
include_once("createZip.inc.php");
$createZip = new createZip; 

// Добавляем директорию
$createZip -> addDirectory("dir/");

// Добавляем файл
$fileContents = file_get_contents("img.jpg")
$createZip -> addFile($fileContents, "dir/img.jpg")

// Создаем архив
$fileName = "archive.zip";
$fd = fopen ($fileName, "wb");
$out = fwrite ($fd, $createZip -> getZippedfile());
fclose ($fd);

// Отдаем архив браузеру
$createZip -> forceDownload($fileName);
@unlink($fileName);
?>

Функция для извлечения файлов из архива:

<?php
/**
 * Распаковывает zip-архив в указанный каталог.
 * $dir  - полный путь к каталогу.
 * $file - полный путь к zip-архиву.
 * $log  - флаг вывода диагностики.
 */

function unpackZip($dir, $file, $log=0) {
    if ($log) echo "Start unpack [$file] into [$dir] directory... <br/>";
 
    if ($zip = zip_open($file)) {
        if ($zip) {
            // создать каталог, если он не существует
            if (! file_exists($dir)) mkdir($dir);
 
            while ($zip_entry = zip_read($zip)) {
                $name = zip_entry_name($zip_entry);
                if ($log) echo "   <b>unpack </b>: $name <br/>";
 
                // последний символ имени
                $last = substr($name, strlen($name)-1);
 
                // если это каталог
                if ($last == "/" || $last == "\\") {
                    $subdir = $dir."/".$name;
                    // создать каталог, если он не существует
                    if (! file_exists($subdir)) mkdir ($subdir);
                } else {
                    // распаковать файл
                    if (zip_entry_open($zip, $zip_entry, "r")) {
                        $buf = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
                        $fp = fopen($dir."/".zip_entry_name($zip_entry), "w");
                        fwrite($fp, $buf);
                        zip_entry_close($zip_entry);
                    } else {
                         return false;
                    }
                }
            }
            zip_close($zip);
        }
    } else {
        return false;
    }
 
    return true;
}
?>

Ссылки по теме: