I have a workbook, which contain 20 worksheets & all worksheets are updating through a php file(a cronjob/scheduler) on a daily basis.
I am facing an issue of duplicate sheets, it is updating existing worksheets but also creating copy of all 20 sheets in each execution. It is increasing file size.
My code:
$styleArray = array( 'borders' => array( 'outline' => array( 'style' => PHPExcel_Style_Border::BORDER_THIN, 'color' => array('argb' => '00000000'),),),);
$excel2 = PHPExcel_IOFactory::createReader('Excel2007');
$excel2 = $excel2->load('mainSites.xlsx');
$row = $excel2->getActiveSheet()->getHighestRow()+1;
$excel2->setActiveSheetIndexByName('sheetname1');
$excel2->getActiveSheet()->setCellValue('A1', 'date')
->setCellValue('B1', 'value1')
->setCellValue('C1', 'value2');
$excel2->getActiveSheet()->getStyle('A1'.':C1')->applyFromArray($styleArray);
$objWriter = new PHPExcel_Writer_Excel2007($excel2);
$objWriter->save('mainSites.xlsx');
from $excel2->setActiveSheetIndexByName('sheetname1');
A loop to pass different sheet name to put data in each sheet.
Please suggest to resolve it.
Thanks
Related
Been pulling my hair out over this for a day and exhausted my google foo. I have inherited a Silverstripe 3.4 site that we have upgraded to 4.4. But something odd has been going on with certain images after running MigrateFilesTask.
I think this is something to do with a file being attached to an unversioned objects that are accessed via ModelAdmin. But I have not been able to find a definitive solution.
Code for this object below. Problems experienced are under it.
<?php
use SilverStripe\Assets\Image;
use gorriecoe\Link\Models\Link;
use SilverStripe\Security\Member;
use SilverStripe\Control\Controller;
use SilverStripe\View\Parsers\URLSegmentFilter;
use SilverStripe\Forms\TextField;
use SilverStripe\Forms\FieldGroup;
use gorriecoe\LinkField\LinkField;
use SilverStripe\TagField\TagField;
use SilverStripe\ORM\DataObject;
use SilverStripe\SelectUpload\SelectUploadField;
class Person extends DataObject
{
private static $db = array(
'FirstName' => 'Varchar(128)',
'LastName' => 'Varchar(128)',
'Role' => 'Varchar(128)',
'DirectDialNumber' => 'Varchar(128)',
'Email' => 'Varchar(128)',
'CellphoneNumber' => 'Varchar(30)',
'DirectDial' => 'Varchar(30)',
'UrlSegment' => 'Varchar(255)',
'Blurb' => 'HTMLText',
'SortOrder' => 'Int'
);
private static $has_one = array(
'Image' => Image::class,
'Office' => 'Office',
'LinkedIn' => Link::class,
'Member' => Member::class
);
private static $many_many = array(
'Interests' => 'Section'
);
private static $belongs_many_many = array(
'ElementCollection' => 'ElementCollection'
);
static $sort_fields = array(
'FirstName' => 'First name',
'LastName' => 'Last name',
'Role' => 'Role'
);
private static $summary_fields = array(
'Name' => 'Name',
'Role' => 'Role',
'Office.Name' => 'Office'
);
private static $searchable_fields = array(
'FirstName',
'LastName',
'Role'
);
// For use with the ElementCollection
public static $templates = array(
'ElementPeople' => 'Default',
'ElementPeopleAlternative' => 'Alternative'
);
public function getCMSFields() {
$fields = parent::getCMSFields();
$fields->removeByName( ['SortOrder', 'ElementCollection', 'FirstName', 'LastName', 'Interests'] );
$firstname = TextField::create('FirstName', 'First name');
$lastname = TextField::create('LastName', 'Last name');
$fields->addFieldsToTab('Root.Main', FieldGroup::create($firstname, $lastname)->setTitle('Name')->setName('Name'), 'Role');
$image = UploadField::create('Image', 'Photo');
$image->setFolderName('Uploads/People');
$image->setCanSelectFolder(false);
$fields->addFieldToTab('Root.Main', $image);
$linkedin = LinkField::create('LinkedIn', 'LinkedIn', $this);
$fields->addFieldToTab('Root.Main', $linkedin);
$interests = TagField::create(
'Interests',
'Interests Tags',
Section::get(),
$this->Interests()
)->setShouldLazyLoad(true)
->setCanCreate(false);
$fields->addFieldToTab('Root.Main', $interests);
return $fields;
}
public function onBeforeWrite()
{
$count = 1;
$this->UrlSegment = $this->generateURLSegment();
while (!$this->validURLSegment()) {
$this->UrlSegment = preg_replace('/-[0-9]+$/', null, $this->UrlSegment) . '-' . $count;
$count++;
}
parent::onBeforeWrite();
}
}
Problem #1 is after running MigrateFileTask, ALL existing images attached to instances of this class get moved from /assets/Uploads/People to /assets/.protected/Uploads/People. The confusing part here is that there is one other class called Company that is structurally near identical, yet images for that remain in /assets/Uploads/Companies as expected.
Problem #2 is if I create a new Person object and attach an image, that image is in Draft, sitting in /assets/.protected/Uploads/People with no method of actually publishing it. Meanwhile, if I do the same with a Company object, the image is still in Draft, but I can see it in the CMS.
Can someone offer some guidance on the above? At this point I'd be happy to just be able for images to be published when the DO is and I'll manually go through every single Person record and hit save myself just to get this upgrade over the line.
You should be able to fix this issue by adding the image to your DataObejct's owns property. Basically add this:
private static $owns = [
'Image'
];
Basically owns tells a DataObject which objects to publish when it is saved:
More info in the docs: https://docs.silverstripe.org/en/4/developer_guides/model/versioning/#defining-ownership-between-related-versioned-dataobjects
The cause of issue #1 was found. Leaving this here in case it helps someone in future:
The database table File has a row for every File and Folder in the system. This table has a column called "CanViewType". It exists in both Silverstripe 3 and 4.
For the particular Folder that was causing trouble during the Migration process, I found it was the only one with that column set to "OnlyTheseUsers". The rest were set to "Inherit". This was the state of the table before the upgrade.
I'm unsure how or by what mechanism that row is ever changed, but the solution to problem #1 was to manually change that field to "Inherit" before running FileMigrationTask.
Issue #2 persists, but it looks like there are two very different issues here.
OK. So sorted problem #2 finally (see other answer for solution to #1), but it's put a massive dent in our confidence in Silverstripe and sparked a meeting here.
Code for future readers:
In your unversioned DataObject, add this. In this case, my file object is called "Image". If you had more than one file to publish on save, you would have to add one of these IF blocks for each.
public function onAfterWrite()
{
if ($this->Image()->exists() && !$this->Image()->isPublished()) {
$this->Image()->doPublish();
}
parent::onAfterWrite();
}
SIDENOTE:
This Object/File relationship really is a strange design choice. Are there actually any situations where you would want to attach a file or image to a data object and NOT publish that file at the same time as you save/publish the object/page? Developers even need to explicitly define that on Versioned objects using $owns - which I'm happy to bet that most developers have to add more times than NOT. Which should really tell a us something is around wrong way.
Adding an image to a CMS system shouldn't be hard. It should take reading basic docs at the most. Not Googling, deep API doc dives (which don't answer much) or posting on StackOverlfow (where no one really knows the answer) over three days. It's an image. A core function of the product.
I've been working with SS since v2.4 and seen all the hard lessons learned to get to v4. But this appears to be a textbook case of the simple being over-engineered.
We move alot of big files and this work flawlessly because this is done in a instance without copying the file. (just moving the pointer)
But sometimes we need acces to the same file from multiple locations in the filesystem, today we copy the file but this takes extremely long time and is storage consuming, this is expected since the file is copied to another place on disk. So we can't complain on this :)
But in our workflow we actually don't have to have multiple files, multiple pointers to the same file is enough. Therefore the hardlink model is perfect choice for us. This would be extremely usefull if it was possible to change the behavior on the copy feature in elfinder, Does anyone know if it is possible. ? :)
It is made possible by extending the elFinderVolumeLocalFileSystem class.
class elFinderVolumeMyLocalFileSystem extends elFinderVolumeLocalFileSystem
{
protected function _copy($source, $targetDir, $name) {
$target = $this->_joinPath($targetDir, $name);
if (! $ret = link($source, $target)) {
return parent::_copy($source, $targetDir, $name);
}
return $ret;
}
}
$opts = array(
'locale' => '',
'roots' => array(
array(
'driver' => 'MyLocalFileSystem',
'path' => '/path/to/files/',
'URL' => 'http://localhost/to/files/'
)
)
);
// run elFinder
$connector = new elFinderConnector(new elFinder($opts));
$connector->run();
While I was trying to show pictures I made this pleasant discovery in backpack:
$this->crud->addFields([
[ // Upload
'name' => 'pictures', //<-- this is an Entity
'label' => 'Photos',
'type' => 'upload_multiple',
'upload' => true,
'disk' => 'uploads'
]
]);
This fragment of code gives me this:
My questions is:
What am I doing wrong?
How can get the value 'file' of this two vectors? I need this for display the images.
You probably forgot to add 'photos' to the cast array.
Based on the documentation:
Step 3. Since the filenames are stored in the database as a JSON array, we're going to use attribute casting on your model, so every time we get the filenames array from the database it's converted from a JSON array to a PHP array:
protected $casts = [
'photos' => 'array'
];
https://laravel-backpack.readme.io/docs/crud-fields#upload_multiple
I'm using FulltextSearchable to search content on my site but I would like to limit
$defaultColumns = array(
'SiteTree' => '"Title","MenuTitle","Content","MetaTitle","MetaDescription","MetaKeywords"',
'File' => '"Title","Filename","Content"'
);
foreach($searchableClasses as $class) {
Config::inst()->update($class, 'create_table_options', array('MySQLDatabase' => 'ENGINE=MyISAM'));
Object::add_extension($class, "FulltextSearchable('{$defaultColumns[$class]}')");
}
How can I limit this search to search 'File' table only for rows which have the 'Deleted' field set to '0'.
You could use something like:
$files = DataObject::get("File","MATCH (Title,Filename,Content) AGAINST ('\"$query\"' IN BOOLEAN MODE) AND Delete = 0");
this is my first post here at stackoverflow and i'll try make sharp and short ;-)
I am running into problems when inserting a textarea form field using CKeditor into the database.
Here is my form element:
$form['add']['description'] = array(
'#wysiwyg' => true,
'#name' => 'description',
'#title' => t('description'),
'#type' => 'text_format',
'#base_type' => 'textarea',
);
When submitting the form i do get a SQL error like this because Drupal appends the placeholder elements 'value' and 'format'
db_insert failed. Message = SQLSTATE[21S01]:
Insert value list does not match column list:
1136 Column count doesn't match value count at row 1,
query= INSERT INTO {tablename} (description)
VALUES (:db_insert_placeholder_13_value, :db_insert_placeholder_13_format)
Unfortunately i exactly have to set up the textarea this way to make the CKeditor work. Can you advice me how to get rid of the
:db_insert_placeholder_13_value,
:db_insert_placeholder_13_format
to a single variable again?
I really appriciate your help
PROBLEM SOLVED --- silly me, should have used my glasses more :-D
Just use the correct array index inside the submit hook for saving the data to the database and it will work:
function MYMODULE_form_add_submit($form, &$form_state) {
...
'description' => $form_state['values']['description']['value'],
...
}
If you're just interested in the text itself (not the format), add a validation handler for the form and use something like this
function MYMODULE_form_name_validate($form, &$form_state) {
$form_state['values']['description'] = $form_state['values']['description']['value'];
}