Plugin Directory

Changeset 3491243


Ignore:
Timestamp:
03/25/2026 08:58:33 PM (3 days ago)
Author:
sightfactory
Message:

Bug fixes and mobile adjustments

Location:
excel-to-elementor/trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • excel-to-elementor/trunk/excel-to-elementor.php

    r3485146 r3491243  
    77 * Plugin URI:        https://sightfactory.com/product/exceltable-for-elementor/
    88 * Description: An Elementor widget to display an Excel spreadsheet file.
    9  * Version: 1.0.7
     9 * Version: 1.0.8
    1010 * Author: Sightfactory
    1111 * Author URI:        https://profiles.wordpress.org/sightfactory/
     
    3131define( 'VWPETE_PLUGIN_DIR', trailingslashit( plugin_dir_path( __FILE__ ) ) );
    3232define( 'VWPETE_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
    33 define( 'VWPETE_VERSION', '1.0.6' );
     33define( 'VWPETE_VERSION', '1.0.8' );
    3434define( 'VWPETE_CACHE_PERIOD', 3600 ); // for future use to cache table 86400.
    3535define( 'VWPETE_EXCEL_CACHE_PREFIX', 'vwpete_excel_table_' );
  • excel-to-elementor/trunk/public/public.css

    r3308621 r3491243  
    11.vwpexcel-table-container {
    2     overflow-y:auto;overflow-x:auto;
     2    width: 100%;
     3}
     4
     5.vwpexcel-table-responsive {
     6    overflow-x: auto;
     7    width: 100%;
     8    -webkit-overflow-scrolling: touch;
     9}
     10
     11#vwpte-excel-table {
     12    width: 100%;
     13    max-width: 100%;
     14    border-collapse: collapse;
    315}
    416
  • excel-to-elementor/trunk/readme.txt

    r3485145 r3491243  
    22Contributors: sightfactory
    33Tags: excel, spreadsheet, elementor, table
    4 Requires at least: 6.3
     4Requires at least: 6.4
    55Tested up to: 6.9
    66Requires PHP: 8.1
    7 Stable tag: 1.0.7
     7Stable tag: 1.0.8
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    1212
    1313== Description ==
    14 Easily import Excel spreadsheets and display them as responsive HTML tables directly in your Elementor pages. This Elementor widget lets you upload .xlsx files, preview the data, and insert clean, styled tables without any coding. Perfect for product lists, schedules, reports, and more.
     14Easily import Excel spreadsheets and display them as responsive HTML tables directly in your Elementor pages. This Elementor widget lets you upload .xls or .xlsx files, preview the data, and insert clean, styled tables without any coding. Perfect for product lists, schedules, reports, and more.
    1515
    1616Features:
    1717
    18 * Upload and import .xlsx Excel files directly into Elementor.
     18* Upload and import .xls or .xlsx Excel files directly into Elementor.
    1919* Instantly convert spreadsheet data into responsive HTML tables.
    2020* Customize table styles using Elementor's native design controls.
     
    3232
    3333= What Excel file formats are supported? =
    34 Currently, only '.xlsx' (OpenXML Spreadsheet) files are supported.
     34Currently, '.xls' (Excel 97-2003) and '.xlsx' (OpenXML Spreadsheet) files are supported.
    3535
    3636= Can I customize the table's appearance? =
     
    5353== Changelog ==
    5454
     55= 1.0.8 =
     56Improved Elementor table responsiveness and added support for .xls files. Fixed Elementor media library restricting selection of previously uploaded .xls / .xlsx files. Fixed PHP 8.1 deprecation notice for trim() during empty cell check.
     57
    5558= 1.0.7 =
    5659Fixed bug where color picker changes were not applied unless another control was toggled.
     
    6770== Upgrade Notice ==
    6871
     72= 1.0.8 =
     73Improves table responsiveness and adds text confirming .xls support. Fixes media library upload bugs and PHP 8.1 deprecation warnings.
     74
    6975= 1.0.7 =
    7076Fixes for color picker controls not applying styles immediately in the Elementor widget.
  • excel-to-elementor/trunk/widgets/class-vwpete-exceltable-to-elementor-widget.php

    r3308621 r3491243  
    1111use Elementor\Controls_Manager;
    1212use PhpOffice\PhpSpreadsheet\IOFactory;
     13use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
    1314
    1415/**
     
    7879        $this->add_control(
    7980            'vwpete_excel_widget',
    80             array(
    81                 'label'       => __( 'Select Excel File', 'excel-to-elementor' ),
    82                 'type'        => \Elementor\Controls_Manager::MEDIA,
    83                 'media_types' => array( 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ),
    84                 'description' => __( 'Choose an Excel file from the media library', 'excel-to-elementor' ),
    85             )
     81            [
     82                'label' => esc_html__( 'Select Excel File', 'excel-to-elementor' ),
     83                'type' => \Elementor\Controls_Manager::MEDIA,
     84                'media_types' => [
     85                    'application',
     86                ],
     87            ]
    8688        );
    8789
     
    192194
    193195        $filetype = wp_check_filetype( $vwpete_excel_widget_url );
    194         if ( 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' !== $filetype['type'] ) {
    195             echo '<div class="elementor-alert elementor-alert-warning">' . esc_html__( 'Selected file is not a valid Excel (.xlsx) file. Please choose a valid Excel (.xlsx) file.', 'excel-to-elementor' ) . '</div>';
     196
     197        if ( 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' !== $filetype['type'] && 'application/vnd.ms-excel' !== $filetype['type'] ) {
     198            echo '<div class="elementor-alert elementor-alert-warning">' . esc_html__( 'Selected file is not a valid Excel (.xls, .xlsx) file. Please choose a valid Excel (.xls, .xlsx) file.', 'excel-to-elementor' ) . '</div>';
    196199            return;
    197200        }
     
    231234        // Ensure it's an Excel file.
    232235        $filetype = wp_check_filetype( $file_path );
    233         if ( 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' !== $filetype['type'] ) {
    234             echo esc_html__( 'Selected file is not a valid Excel (.xlsx) file.', 'excel-to-elementor' );
     236        if ( 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' !== $filetype['type']  && 'application/vnd.ms-excel' !== $filetype['type'] ) {
     237            echo esc_html__( 'Selected file is not a valid Excel (.xls, .xlsx) file.', 'excel-to-elementor' );
    235238            return;
    236239        }
     
    346349            $header_color = sanitize_hex_color( $settings['header_text_color'] ?? '#111111' );
    347350
     351            // Get merged cells information
     352            $merged_cells = $sheet->getMergeCells();
     353            $merged_ranges = array();
     354           
     355            // Parse merged cells into a more usable format
     356            foreach ($merged_cells as $range) {
     357                $range_parts = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::rangeBoundaries($range);
     358                if (count($range_parts) === 2) {
     359                    $start_col = $range_parts[0][0];
     360                    $start_row = $range_parts[0][1];
     361                    $end_col = $range_parts[1][0];
     362                    $end_row = $range_parts[1][1];
     363                   
     364                    // Calculate colspan and rowspan
     365                    $colspan = $end_col - $start_col + 1;
     366                    $rowspan = $end_row - $start_row + 1;
     367                   
     368                    // Store the top-left cell as the key with colspan/rowspan info
     369                    $start_cell = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($start_col) . $start_row;
     370                    $merged_ranges[$start_cell] = array(
     371                        'colspan' => $colspan,
     372                        'rowspan' => $rowspan,
     373                        'end_col' => $end_col,
     374                        'end_row' => $end_row
     375                    );
     376                   
     377                    // Mark all cells in the merged range (except top-left) as merged
     378                    for ($row = $start_row; $row <= $end_row; $row++) {
     379                        for ($col = $start_col; $col <= $end_col; $col++) {
     380                            $cell_coord = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($col) . $row;
     381                            if ($cell_coord !== $start_cell) {
     382                                $merged_ranges[$cell_coord] = array('merged' => true);
     383                            }
     384                        }
     385                    }
     386                }
     387            }
     388
    348389            echo '<div class="vwpexcel-table-container">';
    349390            if ( $use_search ) {
     
    351392            }
    352393
     394            echo '<div class="vwpexcel-table-responsive">';
    353395            echo '<table id="vwpte-excel-table">';
    354396
     397            // Detect the actual data range to skip empty rows/columns
     398            $highest_row = $sheet->getHighestDataRow();
     399            $highest_col = $sheet->getHighestDataColumn();
     400            $highest_col_index = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::columnIndexFromString($highest_col);
     401           
     402            // Find the first non-empty row
     403            $first_data_row = 1;
     404            for ($i = 1; $i <= $highest_row; $i++) {
     405                $row_empty = true;
     406                for ($col_idx = 1; $col_idx <= $highest_col_index; $col_idx++) {
     407                    $col = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($col_idx);
     408                    $cell_value = trim((string)$sheet->getCell($col . $i)->getValue());
     409                    if (!empty($cell_value)) {
     410                        $row_empty = false;
     411                        break;
     412                    }
     413                }
     414                if (!$row_empty) {
     415                    $first_data_row = $i;
     416                    break;
     417                }
     418            }
     419           
     420            // Find the last non-empty row
     421            $last_data_row = $highest_row;
     422            for ($i = $highest_row; $i >= $first_data_row; $i--) {
     423                $row_empty = true;
     424                for ($col_idx = 1; $col_idx <= $highest_col_index; $col_idx++) {
     425                    $col = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($col_idx);
     426                    $cell_value = trim((string)$sheet->getCell($col . $i)->getValue());
     427                    if (!empty($cell_value)) {
     428                        $row_empty = false;
     429                        break;
     430                    }
     431                }
     432                if (!$row_empty) {
     433                    $last_data_row = $i;
     434                    break;
     435                }
     436            }
     437           
     438            // Find the first non-empty column
     439            $first_data_col = 1;
     440            for ($col_idx = 1; $col_idx <= $highest_col_index; $col_idx++) {
     441                $col_empty = true;
     442                $col = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($col_idx);
     443                for ($i = $first_data_row; $i <= $last_data_row; $i++) {
     444                    $cell_value = trim((string)$sheet->getCell($col . $i)->getValue());
     445                    if (!empty($cell_value)) {
     446                        $col_empty = false;
     447                        break;
     448                    }
     449                }
     450                if (!$col_empty) {
     451                    $first_data_col = $col_idx;
     452                    break;
     453                }
     454            }
     455           
     456            // Find the last non-empty column
     457            $last_data_col = $highest_col_index;
     458            for ($col_idx = $highest_col_index; $col_idx >= $first_data_col; $col_idx--) {
     459                $col_empty = true;
     460                $col = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($col_idx);
     461                for ($i = $first_data_row; $i <= $last_data_row; $i++) {
     462                    $cell_value = trim((string)$sheet->getCell($col . $i)->getValue());
     463                    if (!empty($cell_value)) {
     464                        $col_empty = false;
     465                        break;
     466                    }
     467                }
     468                if (!$col_empty) {
     469                    $last_data_col = $col_idx;
     470                    break;
     471                }
     472            }
     473
    355474            $is_header = true;
    356 
    357             foreach ( $sheet->getRowIterator() as $row ) {
     475           
     476            foreach ( $sheet->getRowIterator($first_data_row, $last_data_row) as $row ) {
    358477                $row_index     = $row->getRowIndex();
    359478                $cell_iterator = $row->getCellIterator();
     
    369488                }
    370489
    371                 $tr_style = ' style="background-color: #' . esc_attr( $bg_color ) . ';"';
    372 
    373490                if ( $is_header ) {
    374491                    echo '<thead class="excel-header" style="background-color:' . esc_attr( $header_bg ) . ';color:' . esc_attr( $header_color ) . ';">';
    375492                    echo '<tr>';
    376493                } else {
    377                     echo '<tr' . esc_html( $tr_style ) . '>';
     494                    echo '<tr style="background-color: #' . esc_attr( $bg_color ) . ';">';
    378495                }
    379496
    380497                foreach ( $cell_iterator as $cell ) {
     498                    $cell_coord = $cell->getCoordinate();
     499                    $col_index = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::columnIndexFromString($cell->getColumn());
     500                   
     501                    // Skip columns outside our data range
     502                    if ($col_index < $first_data_col || $col_index > $last_data_col) {
     503                        continue;
     504                    }
     505                   
     506                    // Skip this cell if it's part of a merged range (but not the top-left cell)
     507                    if (isset($merged_ranges[$cell_coord]) && isset($merged_ranges[$cell_coord]['merged'])) {
     508                        continue;
     509                    }
     510                   
    381511                    $cell_value = $cell->isFormula()
    382512                    ? $cell->getCalculatedValue()
    383                     : $spreadsheet->getActiveSheet()->getCell( $cell->getCoordinate() )->getFormattedValue();
     513                    : $spreadsheet->getActiveSheet()->getCell( $cell_coord )->getFormattedValue();
    384514
    385515                    $cell_text   = esc_html( $cell_value );
    386                     $cell_style  = $sheet->getStyle( $cell->getCoordinate() );
     516                    $cell_style  = $sheet->getStyle( $cell_coord );
    387517                    $font        = $cell_style->getFont();
    388518                    $cell_styles = '';
     
    404534                    }
    405535
    406                     $style_attr = $cell_styles ? ' style="' . esc_attr( $cell_styles ) . '"' : '';
     536                    $cspan = '';
     537                    $rspan = '';
     538                   
     539                    // Check if this cell is the top-left of a merged range
     540                    if ( isset( $merged_ranges[ $cell_coord ] ) && isset( $merged_ranges[ $cell_coord ]['colspan'] ) ) {
     541                        $cspan = $merged_ranges[ $cell_coord ]['colspan'];
     542                        $rspan = $merged_ranges[ $cell_coord ]['rowspan'];
     543                    }
    407544
    408545                    if ( $is_header ) {
    409                         echo '<th' . esc_html( $style_attr ) . '>' . esc_html( $cell_text ) . '</th>';
     546                        echo '<th';
    410547                    } else {
    411                         echo '<td' . esc_html( $style_attr ) . '>' . esc_html( $cell_text ) . '</td>';
     548                        echo '<td';
     549                    }
     550
     551                    if ( $cell_styles ) {
     552                        echo ' style="' . esc_attr( $cell_styles ) . '"';
     553                    }
     554                    if ( $cspan ) {
     555                        echo ' colspan="' . esc_attr( $cspan ) . '"';
     556                    }
     557                    if ( $rspan ) {
     558                        echo ' rowspan="' . esc_attr( $rspan ) . '"';
     559                    }
     560                    echo '>';
     561                    echo esc_html( $cell_text );
     562
     563                    if ( $is_header ) {
     564                        echo '</th>';
     565                    } else {
     566                        echo '</td>';
    412567                    }
    413568                }
     
    421576            }
    422577
    423             echo '</table></div>';
     578            echo '</table></div></div>';
    424579
    425580        } catch ( \Throwable $e ) {
Note: See TracChangeset for help on using the changeset viewer.