У меня есть многомерный массив, в котором в некоторых массивах отсутствует пара ключ-значение, которая находится в других массивах. Когда я преобразую в csv (в данном случае, разделенный табуляцией), ячейки столбца в строке сдвигаются влево и заменяют отсутствующий ключ / значение. Например, этот массив:
array
(
array("Make" => "Volvo", "Color" => "red", "Quantity" => 18),
array("Make" => "BMW", "Color" => "blue", "Quantity" => 13),
array("Make" => "Saab", "Quantity" => 11),
array("Make" => "Land Rover", "Color" => "green", "Quantity" => 15)
);
ВЕРСИЯ 1
Когда я использую следующий код:
$cfilename = 'result.csv';
$data = array
(
array("Make" => "Volvo", "Color" => "red", "Quantity" => 18),
array("Make" => "BMW", "Color" => "blue", "Quantity" => 13),
array("Make" => "Saab", "Quantity" => 11),
array("Make" => "Land Rover", "Color" => "green", "Quantity" => 15)
);
//below creates csv
$fp = fopen($cfilename, 'w');
$header = false;
foreach ($data as $row)
{
fputcsv($fp, $row, chr(9));
}
fclose($fp);
return;
Даст мне вывод, как это:
Volvo |red | 18
BMW |blue | 13
Saab |11 |
Land Rover |green | 15
Я могу получить правильное выравнивание столбцов, если использую метки клавиш для написания заголовков. Но в этом случае вместо того, чтобы ячейка для отсутствующей пары ключ / значение была пустой, вместо нее печатается номер столбца.
ВЕРСИЯ 2
Этот код:
$cfilename = 'result.csv';
$data = array
(
array("Make" => "Volvo", "Color" => "red", "Quantity" => 18),
array("Make" => "BMW", "Color" => "blue", "Quantity" => 13),
array("Make" => "Saab", "Quantity" => 11),
array("Make" => "Land Rover", "Color" => "green", "Quantity" => 15)
);
//below creates csv
$fp = fopen($cfilename, 'w');
$header = false;
foreach ($data as $row)
{
if (empty($header)) //creates header, chr(9) makes tab delimited
{
$header = array_keys($row);
fputcsv($fp, $header, chr(9));
$header = array_flip($header);
}
fputcsv($fp, array_merge($header, $row), chr(9)); //creates rows, chr(9) makes tab delimited
}
fclose($fp);
return;
Результаты в этом:
Make | Color | Quantity
-----------|-------|----
Volvo |red | 18
BMW |blue | 13
Saab |1 | 11
Land Rover | green | 15
Обратите внимание, что «1» под цветом в строке «Saab».
Было бы неплохо заставить работать любую версию, если это версия 1, без заголовков, я всегда могу добавить эту строку в выходной файл с разделителями табуляции.
Значение 1
потому что это значение в $header
массив для ключа цвета (вы перевернули его перед слиянием, поэтому вместо 1 => "Color"
, теперь это "Color" => 1
). То, что вы можете сделать, чтобы избавиться от этого, это установить все значения в NULL, или пустую строку, или заполнитель, или все, что вы хотите быть там, когда нет значения, с помощью array_map()
:
<?php
$cfilename = 'result.csv';
$data = array
(
array("Make" => "Volvo", "Color" => "red", "Quantity" => 18),
array("Make" => "BMW", "Color" => "blue", "Quantity" => 13),
array("Make" => "Saab", "Quantity" => 11),
array("Make" => "Land Rover", "Color" => "green", "Quantity" => 15)
);
echo "<pre>";
//below creates csv
$fp = fopen($cfilename, 'w');
$header = false;
foreach ($data as $row)
{
if (empty($header)) //creates header, chr(9) makes tab delimited
{
$header = array_keys($row);
fputcsv($fp, $header, chr(9));
$header = array_flip($header);
$header = array_map(function($header) { return "";}, $header);
}
// var_dump($header);
fputcsv($fp, array_merge($header, $row), chr(9)); //creates rows, chr(9) makes tab delimited
}
fclose($fp);
return;
Почему бы просто не установить поле в пустую строку, если оно не существует?
$cfilename = 'result.csv';
$data = array(
array("Make" => "Volvo", "Color" => "red", "Quantity" => 18),
array("Make" => "BMW", "Color" => "blue", "Quantity" => 13),
array("Make" => "Saab", "Quantity" => 11),
array("Make" => "Land Rover", "Color" => "green", "Quantity" => 15)
);
//below creates csv
$fp = fopen($cfilename, 'w');
$header = false;
$fields = ['Make', 'Color', 'Quantity'];
foreach ($data as $row)
{
foreach($fields as $field) {
if (!array_key_exists($field, $row) {
$row[$field] = '';
}
}
fputcsv($fp, $row, chr(9));
}
fclose($fp);
return;