Using Magmi With Your Magento Store

My work at Aleva Stores has given me some experience with using Magmi to import inventory levels and new products. Creating new products and assigning image, links between simple and configurable products. All a whole lot faster than the default dataflow import system. Not as good as other methods like API Import but good enough for my current uses.

My setup is a generic Magento CE 1.9.0.1 install with the sample data installed. This also assumes that your attributes and attribute sets are created.

Installing and Setting Up Magmi

Setting up Magmi is fairly easy. All you need to do is download the package from the project website. Unzip the file and upload the directory to your root magento directory.  Probably a good idea to put some security on the folder since Magmi has a lot of power and getting access to the system can cause some issues.

Download the Magmi Utilities Plugin zip file. Navigate to the Magmi web interface located at domain.com/magmi/web/magmi.php and use the “Upload New Plugins” section to upload the zip file for the Magmi utilities.

Next fill in the database information under the “Configure Global Parameters” section with the information for your install of Magento and press the ‘save global parameters’ button. You can see the areas I filled in below:

Magmi DB config settings

Quick note on CSV files

The easiest way to create a CSV export file is to create a test product inside Magento and then use the dataflow export to export that product. Then once you have that you can augment the CSV and expand it to include the extra columns for Magmi. At the end of every section I’ll also include links to my example CSV files I created. Save all files in UTF-8 encoding to ease your problems.

All my magmi related fields start at column CC in my CSV files. The other ones are magento default columns and attributes for the default data. Your file may be larger or smaller depending on your setup. And for the most part any non-required columns can be removed from the CSV files.

Importing Simple Products

First create your CSV file of your products. Including the required information and extra fields or attributes that you are using. Upload this file to the magento directory’s var/import folder. If that folder doesn’t exist create one. Here is an example one I created for my test store.

Next under the ‘Configure Current Profile’ section you should create a new profile based off of the default profile. I create a new profile for each type of import I am setting up. One for simple products, one for configurable products and their simples, one for inventory syncs, and so on. Give it a name then press the ‘Copy and Switch’ button.

Profile Creation

The third step is altering the plugins that are used for this profile and the CSV file. For this simple product import I only need to add images. So I select the Image attributes processor plugin. By clicking the configure link for the plugin you can see various options. The only option I changed was Import Image Mode. By changing it to overwrite it will overwrite any changes that are there if the product is new. For most of what I use it for this is the mode I need. Your usage may vary depending on how you are working with it. Once that is done scroll all the way to the bottom and click the save profile button. 

Image Processor Settings

Next upload your images to media/import, if this folder doesn’t exist simply create it. This is the default image import directory, if you alter it in the Image Attributes Processor plugin make sure the images are uploaded to that folder.

The last thing to do is select the file to be imported and the CSV seperator and enclosure items. In the image below you can see that I’ve selected simples.csv for the file to import (the file is located in var/import) and for the seperator I use a comma (,) and for the enclosure I use a pipe (|). I find these to be good settings for my normal usage but how you save your CSV file may differ. For instance you may use the pipe character for meta information so using a tab character (\t) will work better or simply a double quote mark (“). Once you have filled in these options again scroll down and save the profile.

File selection

Once the page refreshes you are now ready to import the file. You can do one of three methods. Update existing items only, skip new ones; create new items & update existing ones; create new items & skip existing ones. Each one has a use. Depending on what you are doing you need to pick the right one. For instance if you have a huge list of new vendor information and only want to update products you already have in your system update only is a good choice. Or if you have that same list but only want to add the products you don’t have in your system the create and skip is a good option. Then if you want to do both create and update is the choice you need to make.

Make sure the profile selected is the one you wish to run and press the run import button.

This is the import screen that you receive when it runs. It will give you some basic output to help you diagnose issues.

Magmi Success Screen

Now you can look at these products in the admin or frontend but you will see one issue. The first image (base/thumbnail/small image) are excluded from the gallery. To fix this just add a plus sign (+) to the base/small/thumbnail image file(s). Depending on your needs again you may want to exclude some of the images  and by default magmi doesn’t include those three. Here is the fixed CSV file.

Also make a note that the image label keeps getting overwritten for each of the products because I used the same image for all three base/thumbnail/small images. Depending on your image setup you may exclude the small and thumbnail images (don’t put a + in front of the image) and have different labels for them.

Importing Configurable Products and Assigning Simple Product Connections

Ok, configurable products are very similar to simple products. A few changes have been made in my configurable product CSV file. The two additions that are magmi related are for the simple sku association and the configurable options. The simple_skus is just a comma separated list of the skus that are being used. The configurable_attributes column is a comma separated list of the attributes being used. In this case it is size and color. Make note the order is important. It will be the order that is displayed on the frontend. Here is the CSV file.

Upload the CSV file and images to var/import and media/import like with the simple product file.

As with the simple products I create a new profile. This one I use to import configurable products and their simple products. So once you create a new one it should be setup exactly like the one you copy it from. In my case I copy and switched from the simple profile. That way the image processor is already setup. So all you need to do is change the file that it will import and setup the configurable product  item processor.

Select the configurable item processor under Product Type Import. Press the configure link for it and make sure the Preform simples/configurables link is set to yes. I personally also set the Force Simples visibility to Not Visible Individually. In our case we set all simples that are part of a configurable product to that setting. If your needs differ then alter it.

Configurable Item Processor

Save the profile and double check the file is correct for the import and let it run on the update method you need for your store. In my case I’m running it with create new items and update existing ones.

Once all of these are done if you followed along this is the result I got on the category page for men’s shirts (the category I put all the products in).

Finial Results

For more information on the product plugins I suggest reading up at the wiki here. That is where I pieced together what I now understand for the system and will eventually go back to learn the bundled and grouped products when the time comes. I may even write a post on creating them when that happens.

In another post I’ll show you how to automate importing quantity updates via a cron job with Magmi (easy inventory syncing).

My experience with Magento Collections so far.

Ok, let me star off by saying I’ve barely scratched the surface of Magento collections but I’ve found them to be a little confusing, and very powerful. So the other day for my job at Discount Party Supplies I had to come up with a solution that would pull tracking numbers that were shipped only by one carrier. Fairly simple and once you grasp how powerful the collections systems are it becomes fairly easy.

First issue tracking down some solid information on Magento Collections. From my experience documentation for Magento is lacking to put it nice. Alan Storm has some good articles and as does Allan MacGregor. Allan MacGregor also has a nice book out, Magento PHP Developer’s Guide. The other places I look frequently are the Magento StackExchange, Magento subreddit, and of course the Magento documentation.

So browsing around I finally find some nice place to start thanks to the IRC room #magento-reddit. There are some awesome people in there that know loads, trust me check it out some time. Starting with the ‘Sales Order Shipment Collection’ I find a way to get tracking numbers and get most of the data I want.

This is what it looks like at first:

	$shipments = Mage::getResourceModel('sales/order_shipment_collection')
		->addAttributeToSelect('*')
		->addAttributeToFilter('main_table.created_at', array(
    		'from' => '2013-09-11 00:00:00',
    		'to' => '2013-09-11 23:59:59'));

Now if you don’t quite understand this I’ll break it down. First we need to tell Magento what resources we are working with, and that is the sales/order_shipment_collection line. Then we have to tell Magento what data we want to select, for this I just wanted all, so I used the ->addAttributeToSelect(‘*’) operator.

Then came the first hurdle for me, getting the filter correct. If you don’t know when you use collections to filter out products, orders, categories, or shipments it gets kinda weird when you want to do a join later on. First thing the first table is main_table inside the SQL statement that will get sent, don’t know why but it is. To test this out you can use the following line to see the SQL statement:

echo $shipments->getSelect();

So now that we have that I knew next I wanted to filter out based on the date for my testing I just used static dates to make it easier on me. This is where the AddAttributeToFilter came into play. Now figuring this out was a pain because Magento has it’s own ways to do this, I recommend using this wiki page as a starting point.

And now I can loop over it and use the method getData() to start finding out where I’m short and what I need to do next.

Now depending on what you need to actually accomplish you may need to do the next part or not.

First issue for me was it gave me every shipment between the time period I stated in the filter. I needed only USPS based orders though so I had to go and find out how to join a table because the carrier was not listed in the shipment table. This was probably the most annoying part because I could not find some resource that explained the join method very well.

After some talks with the great folks in #magento-reddit IRC room I found out that you can’t add a join to the bit of code from above that tells it what to select. You have to add that after the fact and you have to use it after you use the getSelect() method. So this is how I was able to add that join:

$shipments->getSelect()->join("sales_flat_shipment_track", "main_table.entity_id = sales_flat_shipment_track.parent_id", "sales_flat_shipment_track.carrier_code");

Ok, so this just says we are using the same collection from before and we are going to get the SQL then add the join method to it. In my case it was to join with the sales_flat_shipment_tack table so I could also filter out anything that was not USPS shipment.

Now if you are wondering how I got this join to work here is the code I used to do that:

	$shipments = Mage::getResourceModel('sales/order_shipment_collection')
		->addAttributeToSelect('*')
		->addAttributeToFilter('main_table.created_at', array(
    		'from' => '2013-09-11 00:00:00',
    		'to' => '2013-09-11 23:59:59'))
		->addAttributeToFilter("sales_flat_shipment_track.carrier_code", array( "eq"=>"usps" ));
	$shipments->getSelect()->join("sales_flat_shipment_track", "main_table.entity_id = sales_flat_shipment_track.parent_id", "sales_flat_shipment_track.carrier_code");

And as you can expect it was a long process for me to get there. But after that it became very easy to finish this project which was creating a CSV file that had some various bits of information in a nice CSV file so it could be triggered to run every day at some point after shipping is all done.

A simple view of what I had done was this:

$shipments = Mage::getResourceModel('sales/order_shipment_collection')
	->addAttributeToSelect('*')
	->addAttributeToFilter('main_table.created_at', array(
		'from' => '2013-09-11 00:00:00',
    		'to' => '2013-09-11 23:59:59'))
	->addAttributeToFilter("sales_flat_shipment_track.carrier_code", array( "eq"=>"usps" ));
$shipments->getSelect()->join("sales_flat_shipment_track", "main_table.entity_id = sales_flat_shipment_track.parent_id", "sales_flat_shipment_track.carrier_code");
foreach($shipments as $shipment){
	$data = $shipment->getData();
	foreach ($tracking_nums as $tracking) {
		$track_num = $tracking->getNumber();
		//write out the CSV after you have escaped it properly.
	}
}

Daily Programmer Task 102 Intermediate

Daily programmer challenge #102 was to create a program that counted the number of unique characters in a list of words and output the total number that were below a number you give it. My version does that and works like a command line program by passing system arguments. The file it takes should be a text file that can have multiple words on a line.

Useage:

./102_intermediate.py file.txt 4

Output:

Total words with unique characters under or equal to 4 is 10442

Daily Programmer Challenge 102

Well I came across this subreddit, Daily Programmer. The challenge was neat, create a program in whatever language you want that outputs roll results from the input like 1d6+1. I knew I could do it and after about a half hour of toying around I have it working slightly differently in python then the other python ways that are in the thread.

My version, keeps you in a loop until you give the program a blank line. Accepts input with spaces between the numbers, so you could input 1 d 6 + 1 if you wanted. Other versions are in the subreddit thread.

I’ll probably do some of these challenges depending on what looks fun. I hope to do at least one a week though. Plus I learned something new which is what I really cared about. Python ternary style operators.

 a = x if a > x else y

It will set a to x if x is greater than a. Otherwise a becomes y.

Comic list generator

Well I have this compulsion to make lists of things that I am collecting in games or not so when I found out about Ms Marvel I wanted to get all of the that I could. I’ve worked out a simple script that will get them and put them into a CSV file. Usage is simple, put in the title with no spaces when it asks, enter in the url of the list of comics, then how many pages it covers. Only works on marvel pages like Ms Marvel 2006. I’ll eventually expand it a bit more because I know I’ll want to collect other series. Maybe it will be helpful for someone else.

Just an update it will work for DC comics now too like Teen Titans 2011.

If you want a copy of it you can download it here.