First create a Import Button in your Ui-component File
[vendor_name] \ [module_name] \view\adminhtml\ui_component
uiComponenetFileName.xml
<?xml version="1.0" encoding="UTF-8"?>
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Ui/etc/ui_configuration.xsd">
<!-- main part of the grid -->
<argument name="data" xsi:type="array">
<!-- define date source -->
<item name="js_config" xsi:type="array">
<item name="provider" xsi:type="string">locator_record_locator_list.locator_record_locator_list_data_source</item>
<item name="deps" xsi:type="string">locator_record_locator_list.locator_record_locator_list_data_source</item>
</item>
<!-- for columns -->
<item name="spinner" xsi:type="string">locator_records_columns</item>
<!-- for Add new record button -->
<item name="buttons" xsi:type="array">
<item name="add" xsi:type="array">
<item name="name" xsi:type="string">add</item>
<item name="label" xsi:type="string" translate="true">Add New Location</item>
<item name="class" xsi:type="string">primary</item>
<item name="url" xsi:type="string">*/*/addlocation</item>
<item name="sortOrder" xsi:type="number">10</item>
</item>
<item name="import" xsi:type="array">
<item name="name" xsi:type="string">import</item>
<item name="label" xsi:type="string" translate="true">Import Locatore</item>
<item name="class" xsi:type="string">secondary</item>
<item name="url" xsi:type="string">*/dataimport/importdata</item>
<item name="sortOrder" xsi:type="number">20</item>
</item>
<item name="export" xsi:type="array">
<item name="name" xsi:type="string">export</item>
<item name="label" xsi:type="string" translate="true">Export locatore</item>
<item name="class" xsi:type="string">secondary</item>
<item name="url" xsi:type="string">*/*/exportdata</item>
<item name="sortOrder" xsi:type="number">30</item>
</item>
</item>
</argument>
.........................
.........................
.........................
Now this Import Button Call Import Data Form
[vendor_name] \ [module_name] \Controller\Adminhtml\Dataimport
Importdata.php
<?php
namespace [vendor_name]\ [module_name] \Controller\Adminhtml\Dataimport;
use Magento\Framework\Controller\ResultFactory;
class Importdata extends \Magento\Backend\App\Action
{
private $coreRegistry;
public function __construct(
\Magento\Backend\App\Action\Context $context,
\Magento\Framework\Registry $coreRegistry
) {
parent::__construct($context);
$this->coreRegistry = $coreRegistry;
}
public function execute()
{
$rowData = $this->_objectManager->create('[vendor_name] \ [module_name] \Model\Locator');
$this->coreRegistry->register('row_data', $rowData);
$resultPage = $this->resultFactory->create(ResultFactory::TYPE_PAGE);
$resultPage->getConfig()->getTitle()->prepend(__('Import Locator Data'));
return $resultPage;
}
// used for acl.xml
protected function _isAllowed()
{
return $this->_authorization->isAllowed('[vendor_name]_[module_name]::add_datalocation');
}
}
create a Layout File which Call your Block File
[vendor_name] \ [module_name] \view\adminhtml\layout
[controller_name]_dataimport_importdata.xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="content">
<block class="[vendor_name] \ [module_name] \Block\Adminhtml\Dataimport\Importdata" name="importdata_locator" />
</referenceContainer>
</body>
</page>
create a block File for Import Data Form
[vendor_name] \ [module_name] \Block\Adminhtml\Dataimport
Importdata.php
<?php
namespace [vendor_name] \ [module_name] \Block\Adminhtml\Dataimport;
class Importdata extends \Magento\Backend\Block\Widget\Form\Container
{
protected $_coreRegistry = null;
public function __construct(
\Magento\Backend\Block\Widget\Context $context,
\Magento\Framework\Registry $registry,
array $data = []
) {
$this->_coreRegistry = $registry;
parent::__construct($context, $data);
}
protected function _construct()
{
$this->_objectId = 'row_id';
$this->_blockGroup = '[module_name]_[vendor_name]';
$this->_controller = 'adminhtml_dataimport';
parent::_construct();
$this->buttonList->remove('back');
$this->buttonList->update('save', 'label', __('Import'));
$this->buttonList->remove('reset');
$this->addButton(
'backhome',
[
'label' => __('Back'),
'on_click' => sprintf("location.href = '%s';", $this->getUrl('[route_name] / [controller_name] /index')),
'class' => 'back',
'level' => -2
]
);
}
public function getHeaderText()
{
return __('Import Location Data');
}
protected function _isAllowedAction($resourceId)
{
return $this->_authorization->isAllowed($resourceId);
}
public function getFormActionUrl()
{
if ($this->hasFormActionUrl()) {
return $this->getData('form_action_url');
}
return $this->getUrl('[route_name] / dataimport/save');
}
}
the above file call import form
[vendor_name] \ [module_name] \Block\Adminhtml\Dataimport\Edit
Form.php
<?php
namespace [vendor_name] \ [module_name] \Block\Adminhtml\Dataimport\Edit;
use Magento\Framework\View\Asset\Repository;
class Form extends \Magento\Backend\Block\Widget\Form\Generic
{
protected $_assetRepo;
public function __construct(
\Magento\Backend\Block\Template\Context $context,
\Magento\Framework\Registry $registry,
\Magento\Framework\Data\FormFactory $formFactory,
\Magento\Framework\View\Asset\Repository $assetRepo,
array $data = []
) {
parent::__construct($context, $registry, $formFactory, $data);
}
protected function _prepareForm()
{
$path = $this->_assetRepo->getUrl("[vendor_name]_[module_name]::img/[vendor_name]_[module_name]_Sample_File.csv");
$model = $this->_coreRegistry->registry('row_data');
$form = $this->_formFactory->create(
['data' => [
'id' => 'edit_form',
'enctype' => 'multipart/form-data',
'action' => $this->getData('action'),
'method' => 'post'
]
]
);
$form->setHtmlIdPrefix('datalocation_');
$fieldset = $form->addFieldset(
'base_fieldset',
['legend' => __('Import Location '), 'class' => 'fieldset-wide']
);
$importdata_script = $fieldset->addField(
'importdata',
'file',
array(
'label' => 'Upload File',
'required' => true,
'name' => 'importdata',
'note' => 'Allow File type: .csv and .xls',
)
);
$importdata_script->setAfterElementHtml("
<span id='sample-file-span' ><a id='sample-file-link' href='".$path."' >Download Sample File</a></span>
<script type=\"text/javascript\">
document.getElementById('[route_name]_importdata').onchange = function () {
var fileInput = document.getElementById('[route_name]_importdata');
var filePath = fileInput.value;
var allowedExtensions = /(\.csv|\.xls)$/i;
if(!allowedExtensions.exec(filePath))
{
alert('Please upload file having extensions .csv or .xls only.');
fileInput.value = '';
}
};
</script>"
);
$form->setValues($model->getData());
$form->setUseContainer(true);
$this->setForm($form);
return parent::_prepareForm();
}
}
this import form check whether file is valid or not, now create file which read your uploaded file and insert into table .
[vendor_name] \ [module_name] \Controller\Adminhtml\Dataimport*
Save.php
<?php
namespace [vendor_name]\[module_name]\Controller\Adminhtml\Dataimport;
use Magento\Backend\App\Action;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Filesystem;
use Magento\MediaStorage\Model\File\UploaderFactory;
use Magento\Framework\Image\AdapterFactory;
use Magento\Store\Model\ScopeInterface;
class Save extends \Magento\Backend\App\Action
{
protected $fileSystem;
protected $uploaderFactory;
protected $request;
protected $adapterFactory;
public function __construct(
\Magento\Backend\App\Action\Context $context,
\Magento\Framework\Filesystem $fileSystem,
\Magento\MediaStorage\Model\File\UploaderFactory $uploaderFactory,
\Magento\Framework\App\RequestInterface $request,
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
AdapterFactory $adapterFactory
) {
parent::__construct($context);
$this->fileSystem = $fileSystem;
$this->request = $request;
$this->scopeConfig = $scopeConfig;
$this->adapterFactory = $adapterFactory;
$this->uploaderFactory = $uploaderFactory;
}
public function execute()
{
if ( (isset($_FILES['importdata']['name'])) && ($_FILES['importdata']['name'] != '') )
{
try
{
$uploaderFactory = $this->uploaderFactory->create(['fileId' => 'importdata']);
$uploaderFactory->setAllowedExtensions(['csv', 'xls']);
$uploaderFactory->setAllowRenameFiles(true);
$uploaderFactory->setFilesDispersion(true);
$mediaDirectory = $this->fileSystem->getDirectoryRead(DirectoryList::MEDIA);
$destinationPath = $mediaDirectory->getAbsolutePath('[vendor_name]_[module_name]_IMPORTDATA');
$result = $uploaderFactory->save($destinationPath);
if (!$result)
{
throw new LocalizedException
(
__('File cannot be saved to path: $1', $destinationPath)
);
}
else
{
$imagePath = '[vendor_name]_[module_name]_IMPORTDATA'.$result['file'];
$mediaDirectory = $this->fileSystem->getDirectoryRead(DirectoryList::MEDIA);
$destinationfilePath = $mediaDirectory->getAbsolutePath($imagePath);
/* file read operation */
$f_object = fopen($destinationfilePath, "r");
$column = fgetcsv($f_object);
// column name must be same as the Sample file name
if($f_object)
{
if( ($column[0] == 'Col_name_1') && ($column[1] == 'Col_name_2') && ($column[2] == 'Col_name_3') && ($column[3] == 'Col_name_4') && ($column[4] == 'Col_name_5') )
{
$count = 0;
while (($columns = fgetcsv($f_object)) !== FALSE)
{
$rowData = $this->_objectManager->create('Dolphin\Storelocator\Model\Storelocator');
if($columns[0] != 'Col_name_1')// unique Name like Primary key
{
$count++;
/// here this are all the Getter Setter Method which are call to set value
// the auto increment column name not used to set value
$rowData->setCol_name_1($columns[1]);
$rowData->setCol_name_2($columns[2]);
$rowData->setCol_name_3($columns[3]);
$rowData->setCol_name_4($columns[4]);
$rowData->setCol_name_5($columns[5]);
$rowData->save();
}
}
$this->messageManager->addSuccess(__('A total of %1 record(s) have been Added.', $count));
$this->_redirect('[route_name]/[controller_name]/index');
}
else
{
$this->messageManager->addError(__("invalid Formated File"));
$this->_redirect('[route_name]/dataimport/importdata');
}
}
else
{
$this->messageManager->addError(__("File hase been empty"));
$this->_redirect('[route_name]/dataimport/importdata');
}
}
}
catch (\Exception $e)
{
$this->messageManager->addError(__($e->getMessage()));
$this->_redirect('[controller_name]/dataimport/importdata');
}
}
else
{
$this->messageManager->addError(__("Please try again."));
$this->_redirect('[controller_name]/dataimport/importdata');
}
}
}
Now you can Click on the Import Button and upload .csv file and import data.
I Hope This Helps You.
I have finally done this by observer and event.
Admin field where I upload .csv file with format of current admin grid like name,certificationId.
Vendor/Module/etc/adminhtml/System.xml:
<section id="nasmsetting" translate="label" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
<class>separator-top</class>
<label>Nasm Setting</label>
<tab>nasm</tab>
<resource>Vendor_Module::nasm_config</resource>
<group id="nasmgeneral" translate="label" type="text" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1">
<label>General Settings</label>
<field id="nasm_certification_file_upload" translate="label" type="Magento\Config\Block\System\Config\Form\Field\File" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1" >
<label>Upload Latest NASM Table</label>
<backend_model>Magento\Config\Model\Config\Backend\File</backend_model>
<upload_dir config="system" scope_info="1">nasmcustomers</upload_dir>
<comment>Upload new NASM credentials</comment>
</field>
</group></section>
Now Create events.xml:
app/code/Vendor/Module/etc/adminhtml/events.xml
Here I have used "nasmsetting" as defined in system.xml. Which will change/update in admin and call this observer.So event name "admin_system_config_changed_section_nasmsetting"
<?xml version="1.0"?><config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
<event name="admin_system_config_changed_section_nasmsetting">
<observer name="update_latest_nasm_table" instance="Vendor\Module\Observer\Update" />
</event>
Observer where I read .csv and update table data:
app/code/Vendor/Module/Observer/Update.php
<?php
namespace Vendor\Module\Observer;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Vendor\Module\Model\NasmFactory;
class Update implements ObserverInterface
{
protected $messageManager;
protected $_modelNasmFactory;
protected $csv;
public $_storeManager;
protected $_scopeConfig;
public function __construct(
\Magento\Framework\Message\ManagerInterface $messageManager,
NasmFactory $modelNasmFactory,
\Magento\Framework\File\Csv $csv,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
)
{
$this->messageManager = $messageManager;
$this->_modelNasmFactory = $modelNasmFactory;
$this->csv = $csv;
$this->_storeManager = $storeManager;
$this->_scopeConfig = $scopeConfig;
}
/**
* Below is the method that will fire whenever the event runs!
*
* @param Observer $observer
*/
public function execute(Observer $observer)
{
try{
$model = $this->_modelNasmFactory->create();
$storeScope = \Magento\Store\Model\ScopeInterface::SCOPE_STORES;
$uploadedCsvFilePath = $this->_scopeConfig->getValue("nasmsetting/nasmgeneral/nasm_certification_file_upload", $storeScope);
$pubMediaUrl = $this->_storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA);
$uploadedCsv = $pubMediaUrl."nasmcustomers/".$uploadedCsvFilePath;
if($uploadedCsvFilePath != ''){
$handle = fopen($uploadedCsv, "r");
$csv = array_map("str_getcsv", file($uploadedCsv,FILE_SKIP_EMPTY_LINES));
array_shift($csv);
// If NASM IDs exist truncate table
// File uploaded will have IDs already in the database, not just new ones
if (!empty($model)) {
$connection = $model->getResource()->getConnection();
$tableName = $model->getResource()->getMainTable();
$connection->truncateTable($tableName);
}
foreach ($csv as $i=>$row) {
$customerName = $row[0]; //customername
$certificationId = $row[1]; //certificationId
$data = array('nasm_customer_name' => $customerName, 'nasm_code' => $certificationId);
$model->setData($data);
$model->save();
}
}
}catch(Exception $e) {
$writer = new \Zend\Log\Writer\Stream(BP . '/var/log/nasmlog.log');
$logger = new \Zend\Log\Logger();
$logger->addWriter($writer);
$error_message = "Unable to read csv file. Error: " . $e->getMessage() . '. See exception.log for full error log.';
$this->messageManager->addError($error_message);
$logger->info($e);
}
}
}`
Best Answer
I got solution for this. So sharing here:
You have to extend backend model file in your custom module like below: