Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [MySQL][PHP]Eksport do excela - format liczb
Forum PHP.pl > Forum > Przedszkole
Therminus
Php wyświetla mi dane z bazy MySql. Ale potrzebuję też eksport tych danych do Excela (a właściwie do formatu csv).
Znalazłem gdzieś kod, który miał to robić, ale nie działał. Trochę go poprawiłem i Excel już ładnie mi ładuje ten plik csv.
Niestety w obecnej postaci ten plik jest bezużyteczny - liczby nie zawierają przecinków, tylko kropki.
Próbowałem zmusić PHP do zmiany formatu liczb, ale wymiękłem. Może ktoś mi pomóc?

Kod
<?php
    $host = 'localhost';
    $user = 'admin';
    $pass = 'tajne_haslo';
    $db = 'nieruchomosci';
    $table = 'budynki';
    $file = 'bron_12-14';
    
    $link = mysql_connect($host, $user, $pass) or die("Can not connect." . mysql_error());
    mysql_select_db($db) or die("Can not connect.");
    
    mysql_query('SET NAMES CP1250');
    $zapytanie = "SELECT * FROM $table WHERE `ID` LIKE '5' ";
    $result = mysql_query ("SHOW COLUMNS FROM ".$table."");
    $i = 0;
    if (mysql_num_rows($result) > 0)
    {
    while ($row = mysql_fetch_assoc($result))
        {
        $csv_output.= $row['Field'].";";
        $i++;
        }
    }
    $csv_output.= "\n";
    $values = mysql_query($zapytanie);
    $liczba1 = mysql_query("SELECT `Pow_Uzyt` FROM $table WHERE `ID` LIKE '5' ");
    $flicz1 = number_format($liczba1, 2, ',', ' ');
    while ($rowr = mysql_fetch_row($values))
    {
    $csv_output.= "\n";
    for ($j=0;$j<$i;$j++)
        {
        $csv_output.= $rowr[$j].";";
        $flicz1;
        }
     $csv_output.= ";";
    }
    
    $filename = $file."_".date("Y-m-d_H-i",time());
    header("Content-type: application/vnd.ms-excel");
    header("Content-disposition: csv" . date("Y-m-d") . ".csv");
    header("Content-disposition: filename=".$filename.".csv");
    print $csv_output;
    exit;
    ?>


Kolumn z liczbami dziesiętnymi mam 6. Tutaj na razie użyłem tylko jednej `Pow_Uzyt`.
markonix
  1. /**
  2.  * @param string|float $string
  3.  * @param bool $filter Is false then no cast to float but saving formatting
  4.  * @return mixed|string
  5.  */
  6. function float_to_windows_style($string, $filter = true)
  7. {
  8. $float = $filter ? (float) filter_var($string, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION) : $string;
  9. return strlen($string) ? str_replace('.', ',', $float) : '';
  10. }


Lub po prostu
  1. str_replace('.', ',', $float)


borabora
albo number_format z trzecim parametrem
Therminus
Cytat(markonix @ 22.01.2019, 23:06:15 ) *
Lub po prostu
  1. str_replace('.', ',', $float)


Dzięki za zainteresowanie.
Niestety, nie bardzo wiem gdzie to wstawić w kodzie, który mam.
Jakaś podpowiedź?
Tomplus
W ogóle polecam tworzyć tablicę a nie stringi

a następnie użyć funkcji
  1. implode(';', $row);



Sporóbuj w zapytaniu SQL po SELECT dodać coś takiego:
  1. SELECT FORMAT(`Pow_Uzyt`, 2, 'de_DE') `Pow_Uzyt`;
Therminus
Cytat(Tomplus @ 25.01.2019, 07:17:35 ) *
Sporóbuj w zapytaniu SQL po SELECT dodać coś takiego:
  1. SELECT FORMAT(`Pow_Uzyt`, 2, 'de_DE') `Pow_Uzyt`;


Niestety, wymiękam.
Zmienna
Kod
$zapytanie = "SELECT * FROM $table WHERE `ID` LIKE '5' ";

musi być.
Próbowałem utworzyć nową zmienną, a potem podstawić ją w dalszym zapytaniu, ale nie działa.

Kod
$comma = "SELECT FORMAT($zapytanie, 2, 'de_DE')";


Tam dalej w kodzie (patrz pierwszy post) mam utworzoną nową zmienną
Kod
$values = mysql_query($zapytanie);

zatem zrobiłem coś takiego:
Kod
$values = mysql_query($comma);

No i to właśnie nie działa.

Nie wiem, czy dobrze kombinuję, ale myślę, że coś z "SELECT FORMAT" jest nie tak. Generalnie chodzi mi o to, aby tylko liczby dziesiętne były sformatowane przecinkiem (mam jeszcze w tabeli liczby całkowite).
Tomplus
Musisz łyknąć więcej wiedzy na temat zapytań SQL, ja tylko pokazałem przykład, a nie całe poprawne zapytanie, poprawnie będzie gdy dodasz do niego jeszcze FROM i WHERE

  1. $zapytanie = "SELECT FORMAT(`Pow_Uzyt`, 2, 'de_DE') `Pow_Uzyt` FROM {$table} WHERE `ID` = 5;";
  2. $values = mysql_query($zapytanie);


viking
W kodzie masz
  1. $liczba1 = mysql_query("SELECT `Pow_Uzyt` FROM $table WHERE `ID` LIKE '5' ");

Logicznym jest że miałeś to sobie podstawić w tej linii
  1. $liczba1 = mysql_query("SELECT FORMAT(`Pow_Uzyt`, 2, 'de_DE') `Pow_Uzyt` FROM $table WHERE `ID` = 5 ");
Therminus
Tyle się nakombinowałem, a rozwiązanie bardzo proste.
Wklejam cały kod.
  1. <?php
  2. $host = 'localhost';
  3. $user = 'admin';
  4. $pass = 'haslo';
  5. $db = 'nieruchomosci';
  6. $table = 'budynki';
  7. $file = 'bron_12-14';
  8.  
  9. $link = mysql_connect($host, $user, $pass) or die("Can not connect." . mysql_error());
  10. mysql_select_db($db) or die("Can not connect.");
  11.  
  12. mysql_query('SET NAMES CP1250');
  13. $zapytanie = "SELECT * FROM $table WHERE `ID` LIKE '5' ";
  14. $result = mysql_query ("SHOW COLUMNS FROM ".$table."");
  15. $i = 0;
  16. if (mysql_num_rows($result) > 0)
  17. {
  18. while ($row = mysql_fetch_assoc($result))
  19. {
  20. $csv_output.= $row['Field'].";";
  21. $i++;
  22. }
  23. }
  24. $csv_output.= "\n";
  25. $values = mysql_query($zapytanie);
  26. while ($rowr = mysql_fetch_row($values))
  27. {
  28. $csv_output.= "\n";
  29. for ($j=0;$j<$i;$j++)
  30. {
  31. $csv_output.= $rowr[$j].";";
  32. }
  33. $csv_output.= ";";
  34. }
  35. $filename = $file."_".date("Y-m-d_H-i",time());
  36. header("Content-type: application/vnd.ms-excel");
  37. header("Content-disposition: csv" . date("Y-m-d") . ".csv");
  38. header("Content-disposition: filename=".$filename.".csv");
  39. echo str_replace('.', ',', $csv_output);
  40. ?>


Linia nr 39 tylko wymagała poprawy.
Ale jest jeden mały szkopuł.
W jednej kolumnie czasem w tekście pojawia sie kropka i ona jest zamieniana na przecinek.
Nie bardzo mi to pasuje.
Jak zrobić, aby zamiana następowała tylko dla wartości float?
Tomplus
jeżeli dane liczbowe są dobrze zatypowane to wystarczy w pętli while dodać:

  1. if(is_float($rowr[$j])) {
  2. $rowr[$j] = str_replace('.', ',', (string)$rowr[$j]);
  3. }


Warunek sprawdza czy wartość z bazy wyszła jako float.
Therminus
Sorry, pomyłka. Zamroczyło mnie.
Nie mam float, tylko decimal. I tak musi zostać.
będzie gorzej, prawda?
Tomplus
Nie pytaj się tylko sprawdź. Decimal to także liczba zmiennoprzecinkowa.
Therminus
Cytat(Tomplus @ 25.01.2019, 19:20:55 ) *
Nie pytaj się tylko sprawdź. Decimal to także liczba zmiennoprzecinkowa.


Sprawdziłem, ale chyba nie umiem tego wstawić we właściwe miejsce.
Próbowałem is_float i is_numeric.
Nie działa. Mam kropki zamiast przecinków
nospor
@Tomplus
is_float('2.5') nigdy nie zwroci ci true

Dosc ciekawe rozwiazanie podal viking. Czemu go skrzetnie omijacie?
Tomplus
@Nospor
Prawda

A co do rozwiązania Vikinga, to ja go podałem najpierw.
nospor
Cytat
A co do rozwiązania Vikinga, to ja go podałem najpierw.
Tez prawda. Wybacz, jechalem od dolu do gory i stanalem na pierwszym poprawnym rozwiazaniu, ktore w tej kolejnosci padlo na Vikinga smile.gif
Tomplus
Co do:
is_float('2.5') ja zasugerowałem naszemu koledze żeby sprawdził w ogóle jakie dane dostarcza mu baza danych SQL, jeżeli to string to is_float -> FALSE.

@Therminus
Tutaj masz mały eksperyment, możesz sprawdzić działanie u siebie lub np. na takich stronach jak: http://phptester.net/
Wszystkie liczby są stringami lub typu float.

  1. $strings = array('1820.20', 121.21, -12, -100.99, '10002', 'wsl!12', '2.5');
  2. foreach ($strings as $testcase) {
  3. if (is_numeric($testcase)) {
  4. echo "Number: YES. $testcase \n<br>";
  5. } else {
  6. echo "Number: NO. $testcase \n<br>";
  7. }
  8. }


nospor
Cytat
is_float('2.5') ja zasugerowałem naszemu koledze żeby sprawdził w ogóle jakie dane dostarcza mu baza danych SQL,
Jak pobierasz dane z bazy to one sa zawsze STRING nawet jesli w bazie to FLOAT. O to mi chodzilo. Wiec sprawdzanie na danych z bazy is_float nie ma zadnego sensu.



Tomplus
dlatego teraz sugeruję is_numeric smile.gif
Therminus
Cytat(nospor @ 28.01.2019, 13:01:12 ) *
@Tomplus
is_float('2.5') nigdy nie zwroci ci true

Dosc ciekawe rozwiazanie podal viking. Czemu go skrzetnie omijacie?


Rozwiązanie istotnie jest ciekawe i zapytanie SQL rzeczywiście zwraca przecinki, ale takich kolumn z liczbami decimal mam 6.
Nie bardzo widzę możliwość zastosowania tego rozwiązania.
Na początku myślałem, że jak utworzę 6 zmiennych ($liczba1, $liczba2 itd) to mi się na coś przydadzą, ale teraz widzę, że nie.
Tomplus
Pozostaje użyć to w ten sposób:

  1. SELECT
  2. FORMAT(`kolumna_1`, 2, 'de_DE') `kolumna_1`
  3. FORMAT(`kolumna_2`, 2, 'de_DE') `kolumna_2`,
  4. FORMAT(`kolumna_3`, 2, 'de_DE') `kolumna_3`,
  5. FORMAT(`kolumna_4`, 2, 'de_DE') `kolumna_4`,
  6. FORMAT(`kolumna_5`, 2, 'de_DE') `kolumna_5`,
  7. FORMAT(`kolumna_6`, 2, 'de_DE') `kolumna_6`
  8. FROM {$table} WHERE `ID` = 5;


Lub bez formatowania liczb w SQL, a zamiast tego formatujesz w PHP:


tworzysz funkcję:

  1. function numberToExcel($num){
  2. if(is_numeric($num)) {
  3. return str_replace('.', ',', $num);
  4. } else {
  5. return $num;
  6. }
  7. }



a później w pętli ją stosujesz:

  1. {
  2. $csv_output.= numberToExcel($rowr[$j]).";";
  3. }
Therminus
Dzięki @Tomplus

Wszystko działa tak jak chciałem.
Kod całości dla potomności smile.gif

  1. $host = 'localhost';
  2. $user = 'admin';
  3. $pass = 'haslo';
  4. $db = 'nieruchomosci';
  5. $table = 'budynki';
  6. $file = 'nazwa_pliku';
  7. $link = mysql_connect($host, $user, $pass) or die("Can not connect." . mysql_error());
  8. mysql_select_db($db) or die("Can not connect.");
  9.  
  10. mysql_query('SET NAMES CP1250');
  11. $zapytanie = "SELECT * FROM $table WHERE `ID` = '5' ";
  12. $result = mysql_query ("SHOW COLUMNS FROM ".$table."");
  13. $i = 0;
  14. if (mysql_num_rows($result) > 0)
  15. {
  16. while ($row = mysql_fetch_assoc($result))
  17. {
  18. $csv_output.= $row['Field'].";";
  19. $i++;
  20. }
  21.  
  22. }
  23. function numberToExcel($num){
  24. if(is_numeric($num)) {
  25. return str_replace('.', ',', $num);
  26. } else {
  27. return $num;
  28. }
  29. }
  30. $csv_output.= "\n";
  31. $values = mysql_query($zapytanie);
  32. while ($rowr = mysql_fetch_row($values))
  33. {
  34. $csv_output.= "\n";
  35. for ($j=0;$j<$i;$j++)
  36. {
  37. $csv_output.= numberToExcel($rowr[$j]).";";
  38. }
  39. }
  40. $filename = $file."_".date("Y-m-d_H-i",time());
  41. header("Content-type: application/vnd.ms-excel");
  42. header("Content-disposition: csv" . date("Y-m-d") . ".csv");
  43. header("Content-disposition: filename=".$filename.".csv");
  44. echo $csv_output;
Tomplus
Jak zamykasz temat, to najlepiej dać POMÓGŁ osobom które pomogły.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.