Changeset 3491243
- Timestamp:
- 03/25/2026 08:58:33 PM (3 days ago)
- Location:
- excel-to-elementor/trunk
- Files:
-
- 4 edited
-
excel-to-elementor.php (modified) (2 diffs)
-
public/public.css (modified) (1 diff)
-
readme.txt (modified) (5 diffs)
-
widgets/class-vwpete-exceltable-to-elementor-widget.php (modified) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
-
excel-to-elementor/trunk/excel-to-elementor.php
r3485146 r3491243 7 7 * Plugin URI: https://sightfactory.com/product/exceltable-for-elementor/ 8 8 * Description: An Elementor widget to display an Excel spreadsheet file. 9 * Version: 1.0. 79 * Version: 1.0.8 10 10 * Author: Sightfactory 11 11 * Author URI: https://profiles.wordpress.org/sightfactory/ … … 31 31 define( 'VWPETE_PLUGIN_DIR', trailingslashit( plugin_dir_path( __FILE__ ) ) ); 32 32 define( 'VWPETE_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); 33 define( 'VWPETE_VERSION', '1.0. 6' );33 define( 'VWPETE_VERSION', '1.0.8' ); 34 34 define( 'VWPETE_CACHE_PERIOD', 3600 ); // for future use to cache table 86400. 35 35 define( 'VWPETE_EXCEL_CACHE_PREFIX', 'vwpete_excel_table_' ); -
excel-to-elementor/trunk/public/public.css
r3308621 r3491243 1 1 .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; 3 15 } 4 16 -
excel-to-elementor/trunk/readme.txt
r3485145 r3491243 2 2 Contributors: sightfactory 3 3 Tags: excel, spreadsheet, elementor, table 4 Requires at least: 6. 34 Requires at least: 6.4 5 5 Tested up to: 6.9 6 6 Requires PHP: 8.1 7 Stable tag: 1.0. 77 Stable tag: 1.0.8 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 12 12 13 13 == Description == 14 Easily import Excel spreadsheets and display them as responsive HTML tables directly in your Elementor pages. This Elementor widget lets you upload .xls x files, preview the data, and insert clean, styled tables without any coding. Perfect for product lists, schedules, reports, and more.14 Easily 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. 15 15 16 16 Features: 17 17 18 * Upload and import .xls x Excel files directly into Elementor.18 * Upload and import .xls or .xlsx Excel files directly into Elementor. 19 19 * Instantly convert spreadsheet data into responsive HTML tables. 20 20 * Customize table styles using Elementor's native design controls. … … 32 32 33 33 = What Excel file formats are supported? = 34 Currently, only'.xlsx' (OpenXML Spreadsheet) files are supported.34 Currently, '.xls' (Excel 97-2003) and '.xlsx' (OpenXML Spreadsheet) files are supported. 35 35 36 36 = Can I customize the table's appearance? = … … 53 53 == Changelog == 54 54 55 = 1.0.8 = 56 Improved 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 55 58 = 1.0.7 = 56 59 Fixed bug where color picker changes were not applied unless another control was toggled. … … 67 70 == Upgrade Notice == 68 71 72 = 1.0.8 = 73 Improves table responsiveness and adds text confirming .xls support. Fixes media library upload bugs and PHP 8.1 deprecation warnings. 74 69 75 = 1.0.7 = 70 76 Fixes 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 11 11 use Elementor\Controls_Manager; 12 12 use PhpOffice\PhpSpreadsheet\IOFactory; 13 use PhpOffice\PhpSpreadsheet\Cell\Coordinate; 13 14 14 15 /** … … 78 79 $this->add_control( 79 80 '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 ] 86 88 ); 87 89 … … 192 194 193 195 $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>'; 196 199 return; 197 200 } … … 231 234 // Ensure it's an Excel file. 232 235 $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 (.xls x) 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' ); 235 238 return; 236 239 } … … 346 349 $header_color = sanitize_hex_color( $settings['header_text_color'] ?? '#111111' ); 347 350 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 348 389 echo '<div class="vwpexcel-table-container">'; 349 390 if ( $use_search ) { … … 351 392 } 352 393 394 echo '<div class="vwpexcel-table-responsive">'; 353 395 echo '<table id="vwpte-excel-table">'; 354 396 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 355 474 $is_header = true; 356 357 foreach ( $sheet->getRowIterator( ) as $row ) {475 476 foreach ( $sheet->getRowIterator($first_data_row, $last_data_row) as $row ) { 358 477 $row_index = $row->getRowIndex(); 359 478 $cell_iterator = $row->getCellIterator(); … … 369 488 } 370 489 371 $tr_style = ' style="background-color: #' . esc_attr( $bg_color ) . ';"';372 373 490 if ( $is_header ) { 374 491 echo '<thead class="excel-header" style="background-color:' . esc_attr( $header_bg ) . ';color:' . esc_attr( $header_color ) . ';">'; 375 492 echo '<tr>'; 376 493 } else { 377 echo '<tr ' . esc_html( $tr_style ) . '>';494 echo '<tr style="background-color: #' . esc_attr( $bg_color ) . ';">'; 378 495 } 379 496 380 497 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 381 511 $cell_value = $cell->isFormula() 382 512 ? $cell->getCalculatedValue() 383 : $spreadsheet->getActiveSheet()->getCell( $cell ->getCoordinate())->getFormattedValue();513 : $spreadsheet->getActiveSheet()->getCell( $cell_coord )->getFormattedValue(); 384 514 385 515 $cell_text = esc_html( $cell_value ); 386 $cell_style = $sheet->getStyle( $cell ->getCoordinate());516 $cell_style = $sheet->getStyle( $cell_coord ); 387 517 $font = $cell_style->getFont(); 388 518 $cell_styles = ''; … … 404 534 } 405 535 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 } 407 544 408 545 if ( $is_header ) { 409 echo '<th' . esc_html( $style_attr ) . '>' . esc_html( $cell_text ) . '</th>';546 echo '<th'; 410 547 } 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>'; 412 567 } 413 568 } … … 421 576 } 422 577 423 echo '</table></div> ';578 echo '</table></div></div>'; 424 579 425 580 } catch ( \Throwable $e ) {
Note: See TracChangeset
for help on using the changeset viewer.