1

I've created a class that extend the 'FormBase' class to create a form where I can upload a XLSX file to import into custom DB table.

To process the import I would use the 'Drupal batch process' to show to the user the progress of import.

These are the methods I wrote.

    class CommissionerImportUmpiresListForm extends FormBase {

      public function submitForm(array &$form, \Drupal\Core\Form\FormStateInterface $form_state) {
        $form_file = $form_state->getValue('my_file', 0);
        if (isset($form_file[0]) && !empty($form_file[0])) {
          $f = File::load($form_file[0]);
          $f->setPermanent();
          $f->save();
          $this->setSheetData($this->commissioner_read_file($f->getFileURI()));
          $orig = $this->getSheetData();
          $clean = array_shift($orig);
          $this->setSheetData($orig);
          $operations = [];
          $c = count($this->getSheetData());
          foreach ($this->getSheetData() as $row) {
            $operations[] = [
              ['Drupal\commissioner\Form\CommissionerImportUmpiresListForm', 'batch_run'],
              [$row, $c],
            ];
          }

          $batch = [
            'title' => t('Importing the umpires list...'),
            'operations' => $operations,
            'finished' => ['Drupal\commissioner\Form\CommissionerImportUmpiresListForm', 'batch_finished'],
            'init_message' => t('Importing is starting.'),
            'progress_message' => t('Processed @current out of @total.'),
            'error_message' => t('Importing has encountered an error.'),
          ];
          batch_set($batch);
          batch_process('admin/config/content/umpire_list');
        }
      }

      private function commissioner_read_file($file) {
        $sheetData = [];

        try {
          $real_path = \Drupal::service('file_system')->realpath($file);
          $inputFileType = IOFactory::identify($real_path);
          $reader = IOFactory::createReader($inputFileType);
          $spreadsheet = $reader->load($real_path);
          $sheetData = $spreadsheet->getActiveSheet()->toArray(NULL, TRUE, TRUE, TRUE);
        }
        catch (Exception $catch) {
          \Drupal::messenger()->addMessage($catch->getMessage(), \Drupal\Core\Messenger\MessengerInterface::TYPE_ERROR);
        }

        return $sheetData;
      }

      public static function batch_run($row, $count, &$context) {
        if (empty($context['sandbox'])) {
          $context['sandbox']['progress'] = 0;
          $context['sandbox']['max'] = $count;
        }

        $context['sandbox']['progress']++;
        $context['sandbox']['current_umpire'] = $row;

        // Do something with the row.
        $result = \Drupal ::database()
          ->insert('mytable')
          ->fields([
            'cognome' => $row['A'],
            'nome' => $row['B'],
            'categoria' => $row['Z'],
            'qualifica' => $row['AA'],
            'livello' => $row['AB'],
            'comitato' => $row['AC'],
            'email' => $row['T'],
            'cell' => $row['S'],
          ])->execute();

        $context['results'][] = $row;
      }

      public static function batch_finished($success, $results, $operations, $elapsed) {
        if ($success) {
          $message = \Drupal::translation()
            ->formatPlural(count($results), 'One umpire imported.', '@count umpires imported.');
        }
        else {
          $message = t('Finished with an error.');
        }

        \Drupal::messenger()->addMessage($message, \Drupal\Core\Messenger\MessengerInterface::TYPE_STATUS);
      }
    }

I tried executing the form, but after the initial XLSX reader, that created the array with the rows in the file, the batch process doesn't start.

What's wrong? Why doesn't the batch process start?

1

Check out the example on Batch operations. And remove batch_process() from your code. Since you are starting the batch in a form submit handler batch_process() is interrupting that. Just batch_set() and Form API takes care of the rest.

// Only needed if not inside a form _submit handler.
// Setting redirect in batch_process.
batch_process('node/1');

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.