Axapta: Load and Save file from and to container field - axapta

I need to customize AX to load an arbitrary file with arbitrary size and save it to database as a container field. I also need to read back from that container field and write the content into a file, which should contain exactly the same file content as before load.
I had tried with BinaryIO, unfortunately with no luck

The answer to this question applies.
Especially you should use the system class BinData and the methods loadFile and saveFile
.
Example: this job copies the notepad program to a temporary directory.
static void BinDataTest(Args _args)
{
BinData b = new BinData();
Container c;
b.loadFile(#"C:\Windows\notepad.exe");
info(int2str(b.size()));
c = b.getData();
b = new BinData();
b.setData(c);
info(int2str(b.size()));
b.saveFile(#"C:\Temp\notepad.exe");
}

Related

How to upload client file to server?

I need to create form to upload file from client side to server in AX 2012 R3 using X++.
Can some one give me link / example regarding this issue?
I try to search and find that I can use class SysFileStoreManager, but still confused how to use it.
You can find example use of SysFileStoreManager using the Cross-reference Tool. I find it a bit bloated.
You can do this:
static client container getPackedFileClient(FileName _fileNameClient)
{
BinData binData = new BinData();
binData.loadFile(_fileNameClient);
return binData.getData();
}
This is the SysFileStoreManager.getPackedFileClient method, but without the protected keyword.
To save the file:
static server container saveFileToServer(container _packedFile, Filename _filename)
{
#File
BinData b = new BinData();
b.setData(_packedFile);
new FileIOPermission(_filename, #IO_WRITE).assert();
b.saveFile(_filename);
}
This is SysFileStoreManager.copyFileToClient_Client adapted for general use. You can the call the methods in sequence:
saveFileToServer(getPackedFileClient(clienFileName), serverFileName);
The file content is transferred from client to server using a container.

Allow user to copy data from TableView

I have a simple JavaFX app that allows the user to query a database and see the data in a table.
I'd like to allow the user to be able to click a table cell and copy text from that cell to the clipboard with the standard clipboard key stroke: ctrl-c for Win/Linux or cmd-c for Mac. FYI, the text entry controls support basic copy/paste by default.
I'm using the standard javafx.scene.control.TableView class. Is there a simple way to enable cell copy? I did some searches and I see other people create custom menu commands... I don't want to create a custom menu, I just want basic keyboard copy to work with single cells.
I'm using single selection mode, but I can change to something else if need be:
TableView<Document> tableView = new TableView<Document>();
tableView.getSelectionModel().setCellSelectionEnabled(true);
tableView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
You just have to create a listener in the scene, something like:
scene.getAccelerators()
.put(new KeyCodeCombination(KeyCode.C, KeyCombination.CONTROL_ANY), new Runnable() {
#Override
public void run() {
int row = table.getSelectionModel().getSelectedIndex();
DataRow tmp = table.getItems().get(row);
final Clipboard clipboard = Clipboard.getSystemClipboard();
final ClipboardContent content = new ClipboardContent();
if(table.getSelectionModel().isSelected(row, numColumn)){
System.out.println(tmp.getNumSlices());
content.putString(tmp.getNumSlices().toString());
}
else{
System.out.println(tmp.getSelected());
content.putString(tmp.getSelected());
}
clipboard.setContent(content);
}
});
For a complete example, you can download it at the gist.
I recommended that you review this post, work for me
http://respostas.guj.com.br/47439-habilitar-copypaste-tableview-funcionando-duvida-editar-funcionalidade
The author use an aditional util java class for enable the cell content copy from a tableView

How to open text file with the help of button under any form?

I have one text file(Notepad) put under resources node in AX 2012 AOT. Now, my task is to open this file with the help of button under any form.
http://msdn.microsoft.com/en-us/library/cc967403.aspx
Above link is helpful when creating temporary file for writing or reading.
Also, there is a form in AX 2012 named "smmDocuments" in which we can put text files of our use and we can open that file easily from there. I have researched and found that there is a class named "DocuAction" in AX 2012 to perform operations with text files.
But I am unable to understand how that thing is working.
///////////////////
I got it working as:
void clicked()
{
//super();
str sTempPath,
sFileName = "notes.txt";
SysResource::saveToTempFile(SysResource::getResourceNode(resourceStr(flow_for_address_book_txt)), false, "notes.txt");
sTempPath = WinAPI::getTempPath();
WinAPI::shellExecute(sTempPath+sFileName);
}
Thanks Jan B.
You do not describe what actions you want to perform on your file.
Suppose you want to show the file to your user using the default program, then do:
void clicked()
{
SysResource::saveToTempFile(SysResource::getResourceNode(resourceStr(MyImage), false, "notes.txt");
WinAPI::shellExecute("notes.txt");
}
Use a temporary file instead of a hardcoded name.
You may also display the text in a form control:
void clicked()
{
container con = SysResource::getResourceNodeData(SysResource::getResourceNode(resourceStr(MyImage), false, "notes.txt");
infoStringControl.text(conpeek(con,1)); //Not sure how to use the container!
}

Image resizing for image gallery on Tridion 2011

I'm currently working on a web site that will show kind a image gallery on some detail pages. It must show a navigation at the bottom with small thumbnail images and it must show per each element some basic information and the big image.
The big image must be resized too, because there is a maximun size allowed for them.
The point is to use just a source image per multimedia component and being able to resize the images on publishing time so, from the source image would be sent to the client browser a thumbnail and a big image. It's possible to show small and big images using just styles or HTML, but this is quite uneficient because the source (some of them really heavy) image is always sent to the customer.
My first thought was a custom code fragment, something written in C# but I find complicated to resize only some images to a certain size and then resize them again to another size too. I don't find the way to replace the SRC on the final HTML with the appropiate paths neither.
Another idea was to create an old-style PublishBinary method but I find this really complex because looks like the current Tridion architecture is not meant to do this at all...
And the most important point, even in case we can do the resizing succesfully (somehow) it's currently a Tridion 2011 issue to publish twice the same image. Both the big and the small version would came actually from the same multimedia component so shouldn't be possible to publish both of them or playing with the names, the first one would be allways gone, because the path would be updated with the second one :-S.
Any ideas?
I have built an image re-sizing TBB in the past which reads the output of a Dreamweaver or XSLT template. The idea is to produce a tag like the following with the first template.
<img src="tcm:1-123" maxWidth="250" maxHeight="400"
cropPosition="middle" variantId="250x400"
action="PostProcess" enlargeIfTooSmall="true"
/>
The "Re-Sizing" TBB then post processes the Output item in the package, looking for nodes with the PostProcess action.
It then creates a variant of the Multimedia Component using the System.Drawing library according to the maxHieght and maxWidth dimention attributes, and publishes it using the AddBinary() method #frank mentioned and using the variantId attribute for a filename prefix, and variant id (and replaces the SRC attribute with the URL of the new binary).
To make this 100% flexible, if either of the maxHeight or maxWidth attributes are set to 0, the TBB re-sizes based on just the "non-zero" dimension, or if both are set it crops the image based on the cropPosition attribute. This enables us to make sqare thumbnails for both landscape and portrait images without distorting them. The enlargeIfTooSmall attribute is use to prevent small images from being stretched to much.
You can see samples of the final galleries here: http://medicine.yale.edu/web/help/examples/specific/photo/index.aspx
and other image re-sizeing examples here:
http://medicine.yale.edu/web/help/examples/general/images.aspx
All of the images are just uploaded to the CMS once, and then re-sized and cropped on the fly at publish time.
Tridion can perfectly well publish multiple variants on a single MMC. When you call AddBinary you can specify that this binary is a variant of the MMC, with each variant being identified by a simple string that you specify.
public Binary AddBinary(
Stream content,
string filename,
StructureGroup location,
string variantId,
Component relatedComponent,
string mimeType
)
As you can see you can also specify the filename for the binary. If you do, it is your responsibility that variants have unique filenames and filenames between different MMCs remain unique. So typically, it is easiest to simply prefix or suffix the filename with some indication of the variantId: <MmcImageFileName>_thumbnail.jpg.
For a recent demo project, I took a completely different approach. The binaries are all published to a broker database. They are extracted from the broker with an HttpModule, which writes the binary data to the file system.
I made it possible to encode the desired width or height in the URL of the image (of course, for binaries that are not images this part of the logic will not work). The module then resizes the image on the fly (truly on the fly, not during publishing!) and writes the resized version to the disk.
For example: if I request /Images/photo.jpg, I will get the original image. If I request /Images/photo_h100.jpg, I get a version of 100 pixels high. The url /Images/photo_w150.jpg leads to a width of 150 pixels.
No variants needed, no republishing because of different size requirements either: resizing is completely done on demand! The performance penalty on the server is negligible: each size is generated only once, until the image is republished.
I used .NET, but of course it can work in Java as well.
Following the Frank's and Quirijn's answer you may be interested on resize the image in a Cartridge Claims processor using the Ambient Data Framework. This solution would be technology agnostic and can be re-used in both Java and .Net. You just need to put the resized image bytes in a Claim and then use it in Java or .Net.
Java Claims Processor:
public void onRequestStart(ClaimStore claims) throws AmbientDataException {
int publicationId = getPublicationId();
int binaryId = getBinaryId();
BinaryContentDAO bcDAO = (BinaryContentDAO)StorageManagerFactory.getDAO(publicationId, StorageTypeMapping.BINARY_CONTENT);
BinaryContent binaryContent = bcDAO.findByPrimaryKey(publicationId, binaryId, null);
byte[] binaryBuff = binaryContent.getContent();
pixelRatio = getPixelRatio();
int resizeWidth = getResizeWidth();
BufferedImage original = ImageIO.read(new ByteArrayInputStream(binaryBuff));
if (original.getWidth() < MAX_IMAGE_WIDTH) {
float ratio = (resizeWidth * 1.0f) / (float)MAX_IMAGE_WIDTH;
float width = original.getWidth() * ratio;
float height = original.getHeight() * ratio;
BufferedImage resized = new BufferedImage(Math.round(width), Math.round(height), original.getType());
Graphics2D g = resized.createGraphics();
g.setComposite(AlphaComposite.Src);
g.drawImage(original, 0, 0, resized.getWidth(), resized.getHeight(), null);
g.dispose();
ByteArrayOutputStream output = new ByteArrayOutputStream();
BinaryMeta meta = new BinaryMetaFactory().getMeta(String.format("tcm:%s-%s", publicationId, binaryId));
String suffix = meta.getPath().substring(meta.getPath().lastIndexOf('.') + 1);
ImageIO.write(resized, suffix, output);
binaryBuff = output.toByteArray();
}
claims.put(new URI("taf:extensions:claim:resizedimage"), binaryBuff);
}
.Net HTTP Handler:
public void ProcessRequest(HttpContext context) {
if (context != null) {
HttpResponse httpResponse = HttpContext.Current.Response;
ClaimStore claims = AmbientDataContext.CurrentClaimStore;
if (claims != null) {
Codemesh.JuggerNET.byteArray javaArray = claims.Get<Codemesh.JuggerNET.byteArray>("taf:extensions:claim:resizedimage");
byte[] resizedImage = javaArray.ToNative(javaArray);
if (resizedImage != null && resizedImage.Length > 0) {
httpResponse.Expires = -1;
httpResponse.Flush();
httpResponse.BinaryWrite(resizedImage);
}
}
}
}
Java Filter:
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
ClaimStore claims = AmbientDataContext.getCurrentClaimStore();
if (claims != null) {
Object resizedImage = claims.get(new URI("taf:extensions:claim:resizedimage"));
if (resizedImage != null) {
byte[] binaryBuff = (byte[])resizedImage;
response.getOutputStream().write(binaryBuff);
}
}
}

Convert CSV file or Excel spreadsheet to RESX File

I am looking for a solution or recommendation to a problem I am having. I have a bunch of ASPX pages that will be localized and have a bunch of text that needs to be supported in 6 languages.
The people doing the translation will not have access to Visual Studio and the likely easiest tool is Excel. If we use Excel or even export to CSV, we need to be able to import to move to .resx files. So, what is the best method for this?
I am aware of this question, Convert a Visual Studio resource file to a text file? already and the use of Resx Editor but an easier solution would be preferred.
I'm not sure how comprehensive an answer you're looking for, but if you're really just using [string, string] pairs for your localization, and you're just looking for a quick way to load resource (.resx) files with the results of your translations, then the following will work as a fairly quick, low-tech solution.
The thing to remember is that .resx files are just XML documents, so it should be possible to manually load your data into the resource from an external piece of code. The following example worked for me in VS2005 and VS2008:
namespace SampleResourceImport
{
class Program
{
static void Main(string[] args)
{
XmlDocument doc = new XmlDocument();
string filePath = #"[file path to your resx file]";
doc.Load(filePath);
XmlElement root = doc.DocumentElement;
XmlElement datum = null;
XmlElement value = null;
XmlAttribute datumName = null;
XmlAttribute datumSpace = doc.CreateAttribute("xml:space");
datumSpace.Value = "preserve";
// The following mocks the actual retrieval of your localized text
// from a CSV or ?? document...
// CSV parsers are common enough that it shouldn't be too difficult
// to find one if that's the direction you go.
Dictionary<string, string> d = new Dictionary<string, string>();
d.Add("Label1", "First Name");
d.Add("Label2", "Last Name");
d.Add("Label3", "Date of Birth");
foreach (KeyValuePair<string, string> pair in d)
{
datum = doc.CreateElement("data");
datumName = doc.CreateAttribute("name");
datumName.Value = pair.Key;
value = doc.CreateElement("value");
value.InnerText = pair.Value;
datum.Attributes.Append(datumName);
datum.Attributes.Append(datumSpace);
datum.AppendChild(value);
root.AppendChild(datum);
}
doc.Save(filePath);
}
}
}
Obviously, the preceding method won't generate the code-behind for your resource, however opening the resource file in Visual Studio and toggling the accessibility modifier for the resource will (re)generate the static properties for you.
If you're looking for a completely XML-based solution (vs. CSV or Excel interop), you could also instruct your translators to store their translated content in Excel, saved as XML, then use XPath to retrieve your localization info. The only caveat being the file sizes tend to become pretty bloated.
Best of luck.
I ran into similar problem and realized that the simplest way to create a .resx file from excel file is using a concatenate function of excel to generate "<"data">".."<"/data">" node for the .resx file and then manually copying the generated rows to the .resx file in any text editor. So lets say that you have "Name" in column A of an excel document and "value" in Column B of the excel document. Using following formula in Column C
=CONCATENATE("<data name=","""",A14,""" xml:space=""preserve"">","<value>", B14, "</value>", "</data>")
you will get the data node for resource. You can then copy this formula to all the rows and then copy the contents of Column C in your .resx file.
If it's in csv here's a quick Ruby script to generate the data elements.
require 'csv'
require 'builder'
file = ARGV[0]
builder = Builder::XmlMarkup.new(:indent => 2)
CSV.foreach(file) do |row|
builder.data(:name => row[0], "xml:space" => :preserve) {|d| d.value(row[1]) }
end
File.open(file + ".xml", 'w') { |f| f.write(builder.target!) }

Resources