Giter Site home page Giter Site logo

pyexcel-ods3's Introduction

pyexcel-ods3 - Let you focus on data, instead of ods format

image

image

image

image

image

image

image

image

image

image

image

pyexcel-ods3 is a tiny wrapper library to read, manipulate and write data in ods format. You are likely to use pyexcel together with this library. pyexcel-ods is a sister library that depends on GPL licensed odfpy. pyexcel-odsr is the other sister library that has no external dependency but do ods reading only

Support the project

If your company has embedded pyexcel and its components into a revenue generating product, please support me on github, patreon or bounty source to maintain the project and develop it further.

If you are an individual, you are welcome to support me too and for however long you feel like. As my backer, you will receive early access to pyexcel related contents.

And your issues will get prioritized if you would like to become my patreon as pyexcel pro user.

With your financial support, I will be able to invest a little bit more time in coding, documentation and writing interesting posts.

Known constraints

Fonts, colors and charts are not supported.

Nor to read password protected xls, xlsx and ods files.

Installation

You can install pyexcel-ods3 via pip:

$ pip install pyexcel-ods3

or clone it and install it:

$ git clone https://github.com/pyexcel/pyexcel-ods3.git
$ cd pyexcel-ods3
$ python setup.py install

Usage

As a standalone library

>>> import os >>> import sys >>> if sys.version_info[0] < 3: ... from StringIO import StringIO ... else: ... from io import BytesIO as StringIO >>> PY2 = sys.version_info[0] == 2 >>> if PY2 and sys.version_info[1] < 7: ... from ordereddict import OrderedDict ... else: ... from collections import OrderedDict

Write to an ods file

Here's the sample code to write a dictionary to an ods file:

>>> from pyexcel_ods3 import save_data
>>> data = OrderedDict() # from collections import OrderedDict
>>> data.update({"Sheet 1": [[1, 2, 3], [4, 5, 6]]})
>>> data.update({"Sheet 2": [["row 1", "row 2", "row 3"]]})
>>> save_data("your_file.ods", data)

Read from an ods file

Here's the sample code:

>>> from pyexcel_ods3 import get_data
>>> data = get_data("your_file.ods")
>>> import json
>>> print(json.dumps(data))
{"Sheet 1": [[1, 2, 3], [4, 5, 6]], "Sheet 2": [["row 1", "row 2", "row 3"]]}

Write an ods to memory

Here's the sample code to write a dictionary to an ods file:

>>> from pyexcel_ods3 import save_data
>>> data = OrderedDict()
>>> data.update({"Sheet 1": [[1, 2, 3], [4, 5, 6]]})
>>> data.update({"Sheet 2": [[7, 8, 9], [10, 11, 12]]})
>>> io = StringIO()
>>> save_data(io, data)
>>> # do something with the io
>>> # In reality, you might give it to your http response
>>> # object for downloading

>>> notneeded=io.seek(0)

Read from an ods from memory

Continue from previous example:

>>> # This is just an illustration
>>> # In reality, you might deal with ods file upload
>>> # where you will read from requests.FILES['YOUR_ODS_FILE']
>>> data = get_data(io)
>>> print(json.dumps(data))
{"Sheet 1": [[1, 2, 3], [4, 5, 6]], "Sheet 2": [[7, 8, 9], [10, 11, 12]]}

Pagination feature

Special notice 30/01/2017: due to the constraints of the underlying 3rd party library, it will read the whole file before returning the paginated data. So at the end of day, the only benefit is less data returned from the reading function. No major performance improvement will be seen.

With that said, please install pyexcel-odsr and it gives better performance in pagination.

Let's assume the following file is a huge ods file:

>>> huge_data = [
...     [1, 21, 31],
...     [2, 22, 32],
...     [3, 23, 33],
...     [4, 24, 34],
...     [5, 25, 35],
...     [6, 26, 36]
... ]
>>> sheetx = {
...     "huge": huge_data
... }
>>> save_data("huge_file.ods", sheetx)

And let's pretend to read partial data:

>>> partial_data = get_data("huge_file.ods", start_row=2, row_limit=3)
>>> print(json.dumps(partial_data))
{"huge": [[3, 23, 33], [4, 24, 34], [5, 25, 35]]}

And you could as well do the same for columns:

>>> partial_data = get_data("huge_file.ods", start_column=1, column_limit=2)
>>> print(json.dumps(partial_data))
{"huge": [[21, 31], [22, 32], [23, 33], [24, 34], [25, 35], [26, 36]]}

Obvious, you could do both at the same time:

>>> partial_data = get_data("huge_file.ods",
...     start_row=2, row_limit=3,
...     start_column=1, column_limit=2)
>>> print(json.dumps(partial_data))
{"huge": [[23, 33], [24, 34], [25, 35]]}

>>> os.unlink("huge_file.ods")

As a pyexcel plugin

No longer, explicit import is needed since pyexcel version 0.2.2. Instead, this library is auto-loaded. So if you want to read data in ods format, installing it is enough.

Reading from an ods file

Here is the sample code:

>>> import pyexcel as pe
>>> sheet = pe.get_book(file_name="your_file.ods")
>>> sheet
Sheet 1:
+---+---+---+
| 1 | 2 | 3 |
+---+---+---+
| 4 | 5 | 6 |
+---+---+---+
Sheet 2:
+-------+-------+-------+
| row 1 | row 2 | row 3 |
+-------+-------+-------+

Writing to an ods file

Here is the sample code:

>>> sheet.save_as("another_file.ods")

Reading from a IO instance

You got to wrap the binary content with stream to get ods working:

>>> # This is just an illustration
>>> # In reality, you might deal with ods file upload
>>> # where you will read from requests.FILES['YOUR_ODS_FILE']
>>> odsfile = "another_file.ods"
>>> with open(odsfile, "rb") as f:
...     content = f.read()
...     r = pe.get_book(file_type="ods", file_content=content)
...     print(r)
...
Sheet 1:
+---+---+---+
| 1 | 2 | 3 |
+---+---+---+
| 4 | 5 | 6 |
+---+---+---+
Sheet 2:
+-------+-------+-------+
| row 1 | row 2 | row 3 |
+-------+-------+-------+

Writing to a StringIO instance

You need to pass a StringIO instance to Writer:

>>> data = [
...     [1, 2, 3],
...     [4, 5, 6]
... ]
>>> io = StringIO()
>>> sheet = pe.Sheet(data)
>>> io = sheet.save_to_memory("ods", io)
>>> # then do something with io
>>> # In reality, you might give it to your http response
>>> # object for downloading

License

New BSD License

Developer guide

Development steps for code changes

  1. git clone https://github.com/pyexcel/pyexcel-ods3.git
  2. cd pyexcel-ods3

Upgrade your setup tools and pip. They are needed for development and testing only:

  1. pip install --upgrade setuptools pip

Then install relevant development requirements:

  1. pip install -r rnd_requirements.txt # if such a file exists
  2. pip install -r requirements.txt
  3. pip install -r tests/requirements.txt

Once you have finished your changes, please provide test case(s), relevant documentation and update changelog.yml

Note

As to rnd_requirements.txt, usually, it is created when a dependent library is not released. Once the dependecy is installed (will be released), the future version of the dependency in the requirements.txt will be valid.

How to test your contribution

Although nose and doctest are both used in code testing, it is adviable that unit tests are put in tests. doctest is incorporated only to make sure the code examples in documentation remain valid across different development releases.

On Linux/Unix systems, please launch your tests like this:

$ make

On Windows, please issue this command:

> test.bat

Before you commit

Please run:

$ make format

so as to beautify your code otherwise your build may fail your unit test.

Installation Note

The installation of lxml will be tricky on Windows platform. It is recommended that you download a lxml's own windows installer instead of using pip.

>>> import os >>> os.unlink("your_file.ods") >>> os.unlink("another_file.ods")

pyexcel-ods3's People

Contributors

bwaldvogel avatar chfw avatar fuhrysteve avatar matkoniecz avatar michael-k avatar vinraspa avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

pyexcel-ods3's Issues

datetime (dates) from ODS can't be serialized by json...,

I followed the readme.md example.

json.dump(data) failed, because one of the ODS sheet contained a date value.

Since dates are so popular in spreadsheets, I recommend:

  1. adding a comment in the readme, that this example fails with date values.
  2. Read datetime objects into a subclass (e.g. of datetime or other modern date objects), with a default, serialize-able data representation / casting (string, numeric value, named-tuple).

e.g.

(I have no clue what method is called by JSON.dumps on a non-built-in class)

# pseudo-code ahead:
class excel_datetime(datetime):
    def __repr__(self):
        fmt = self.default_date_format
        return strftime(self.data, fmt)

Hope this suggestion makes sense.

My aim is to make a default, minimal code data dumping of ods files.

This could be overridden by the user, on the constructor, e.g.

>>> from pyexcel_ods3 import get_data
>>> data = get_data("your_file.ods", date_representation='string', dateformat='yyyy-mm-dd')
>>> import json
>>> print(json.dumps(data))
# example of datetime formatted as string:
{"Sheet 1": [[1, '2019-12-31', 3], ]}

or

# example of datetime as decimal number:
{"Sheet 1": [[1, 1603093971.1975482, 3], ]}

thanks!

Tries to call cell.split("\n") on datetime column

I am trying to save a datetime object to an ODS file, which produces:

  File "/home/madduck/.local/lib/python3.9/site-packages/pyexcel_ods/odsw.py", line 47, in write_cell
    lines = cell.split("\n")
AttributeError: 'datetime.datetime' object has no attribute 'split'

I could use strftime, but I don't want to store a string, but a timestamp. Am I doing something wrong?

Empty cells are ignored

Hi, the get_data() method returns a list for each row.
The list contains only the values of non empty cells.
When parsing a table it may be necessary to know if a cell was empty.
I suggest to add and option the get_data() method so to include an empty string (or None value) for empty cells into the returned lists.

Ghost rows and columns when using decorations (colors/borders)

import pyexcel_ods3
print(pyexcel_ods3.get_data('test.ods', keep_trailing_empty_cells=True))

test.ods contains a simple table

A1,B1
A2,B2

OrderedDict([('Sheet1', [['A1', 'B1'], ['A2', 'B2']])])

If add color to these 4 cells, the output of print is the same.
I add a color to the 3th row, I get a new "empty" row as output, an that's fine:
OrderedDict([('Sheet1', [['A1', 'B1'], ['A2', 'B2'], ['', ''], ['', '']])])

I remove the color from the 3th row by clicking to "No fill", I still get
OrderedDict([('Sheet1', [['A1', 'B1'], ['A2', 'B2'], ['', ''], ['', '']])])

I guess 'No fill' doesn't really remove the color info.
Removing the row by right click, does the job, no more empty row.
OrderedDict([('Sheet1', [['A1', 'B1'], ['A2', 'B2']])])

Now the more interesting part: click on column "A" (selection goes till the end of the sheet), add a color and print the table:
OrderedDict([('Sheet1', [['A1', 'B1'], ['A2', 'B2'], ['', ''], ['', '']])])

We get an extra empty row.
Now, if I remove the color form the whole column, I still get the empty row.
I shall remove column A to get rid of it but in such case I loose data.

OrderedDict([('Sheet1', [['B1'], ['B2']])])

Well, the issue is probably the same or very similar to the first case, bu in this case I have no way to work around it.
You get the very same issue if you add borders (or color) to cells C1, C2.
There are no values on these cells and you get
OrderedDict([('Sheet1', [['a1', 'b1', ''], ['a2', 'b2', '']])])
and this is fine.

Removing borders or colors is not going to remove the empty column, you have to right click and delete the column.

If select the whole rows 1 and 2, add color, the remove it, you can't get rid of the "empty" column (right click / delete on column "C" is not going to help).
OrderedDict([('Sheet1', [['a1', 'b1', ''], ['a2', 'b2', '']])])

So I think pyexcel3 shall handle cell where decorations have been totally remove and shall ignore decorations of whole rows or columns.

Handling merged cells

I am trying to load a .ods file to memory which has merged cells and when I write back, the merged cells are not retained anymore.

Any future plan to support merged cells ?

Can't import

When I try the test code

from pyexcel_ods3 import save_data
data = OrderedDict() # from collections import OrderedDict
data.update({"Sheet 1": [[1, 2, 3], [4, 5, 6]]})
data.update({"Sheet 2": [["row 1", "row 2", "row 3"]]})
save_data("your_file.ods", data)

... it won't import pyexcel_ods3. I already did pip install pyexcel-ods3 after installing pyexcel.

Support for images

Support for images within a sheet.

example: cell D3 contains an image, when requesting the value of this cell then one of the following should be returned:

  • image object
  • or reference to image that could be used to open image with other python library

edit and Save the file

import pyexcel_ods3

data = pyexcel_ods3.get_data("foo.ods")

pyexcel_ods3.save_data("new1.ods",data)

I Dont't want to New file. i want to edit file the and save the file

Dictionaries instead of lists

Hi, I think it's a common case to have a single table per sheet, with column labels (like in csv files).
This is not a bug report but more an enhancement discussion.
I wonder if it could be possible to have an argument like csv-style=True to pass to get_data() method.
This option assumes that all sheets have a single table and the first row contains column labels.
Doing so, instead of representing a sheet like a list of lists, it could be represented as a list of dictionaries, exactly how it happens with the csv.DictReader in the standard library.

The main advantage of using dictionaries is the possibility of altering the column order of the file, without the need to change the script code because cells are referenced by a key.

Let me know what you think about it please.
Thank you.

Cannot read from url: AttributeError: addinfourl instance has no attribute 'seek'

tibility.py", line 67, in is_zipfile
    return zipfile.is_zipfile(data)
  File "/usr/lib64/python2.7/zipfile.py", line 150, in is_zipfile
    result = _check_zipfile(fp=filename)
  File "/usr/lib64/python2.7/zipfile.py", line 136, in _check_zipfile
    if _EndRecData(fp):
  File "/usr/lib64/python2.7/zipfile.py", line 208, in _EndRecData
    fpin.seek(0, 2)
AttributeError: addinfourl instance has no attribute 'seek'

pyexcel/pyexcel-xls#20

Python 3.10 save_data to StringIO error TypeError: string argument expected, got 'bytes'

Writing to memory example from the README.md doesn't work in Python3.10.

>>> from pyexcel_ods3 import save_data
>>> data = OrderedDict()
>>> data.update({"Sheet 1": [[1, 2, 3], [4, 5, 6]]})
>>> data.update({"Sheet 2": [[7, 8, 9], [10, 11, 12]]})
>>> io = StringIO()
>>> save_data(io, data)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/ondrej/logistic/backend/venv/lib64/python3.10/site-packages/pyexcel_ods3/__init__.py", line 43, in save_data
    write_data(afile, data, file_type=file_type, **keywords)
  File "/home/ondrej/logistic/backend/venv/lib64/python3.10/site-packages/pyexcel_io/io.py", line 142, in save_data
    with get_writer(**keywords) as writer:
  File "/home/ondrej/logistic/backend/venv/lib64/python3.10/site-packages/pyexcel_io/writer.py", line 51, in __exit__
    self.close()
  File "/home/ondrej/logistic/backend/venv/lib64/python3.10/site-packages/pyexcel_io/writer.py", line 45, in close
    self.writer.close()
  File "/home/ondrej/logistic/backend/venv/lib64/python3.10/site-packages/pyexcel_ods3/odsw.py", line 114, in close
    self.ods_book.save()
  File "/home/ondrej/logistic/backend/venv/lib64/python3.10/site-packages/ezodf/document.py", line 125, in save
    self._saving_routine()
  File "/home/ondrej/logistic/backend/venv/lib64/python3.10/site-packages/ezodf/document.py", line 233, in _saving_routine
    self.filemanager.save(self.docname, backup=self.backup)
  File "/home/ondrej/logistic/backend/venv/lib64/python3.10/site-packages/ezodf/filemanager.py", line 88, in save
    self._tozip(zippo)
  File "/home/ondrej/logistic/backend/venv/lib64/python3.10/site-packages/ezodf/filemanager.py", line 144, in _tozip
    zippo.writestr(mimetype.zipinfo, mimetype.tobytes())
  File "/usr/lib64/python3.10/zipfile.py", line 1814, in writestr
    with self.open(zinfo, mode='w') as dest:
  File "/usr/lib64/python3.10/zipfile.py", line 1517, in open
    return self._open_to_write(zinfo, force_zip64=force_zip64)
  File "/usr/lib64/python3.10/zipfile.py", line 1612, in _open_to_write
    self.fp.write(zinfo.FileHeader(zip64))
TypeError: string argument expected, got 'bytes'

The system can not handle with empty cells and sheets

Hi all,

I use the pyexcel-ods3 and I have a problem. The system can't handle with empty cells and empty sheets.
If you read a file with empty sheet, you get {'SheetName' : []} If you want to write it with odsw.py you get an exception. The system can't write his own generated dict.
The other Problem is that I can't write empty cells, only cells with an empty string. It is not the same, you can see the different. The row 1 has cells with empty strings, the second row has empty cells.
Effect
The odsw.py can accept a row ['text','','','other text'] but not ['text',None,None,'other text']

I repared it for myself and I think it can be usefull for others also.

I changed 4 files in 3 projects. They are the service.py in the pyexcel.io; cells.py in the pyexcel-ezodf; the odsr.py and odsw.py in the pyexcel-ods3.

The service.py in pyexcel-io is the deepest place. I need there in the dict ODS_WRITE_FORMAT_COVERSION a new item in the row 178: type(None): "nothing",

I inserted in pyexcel-ezodf/ezodf in the file cells.py in the rows 78, 79 (or only in the line 78 if you like it) elif t == 'nothing': result = None The value will be None if the cell is empty, and you don't get "" back any more. If you have 3 empty cells in a row, then you get [None,None,None,'text'] and not ['','','','text']

The line 55 in the file odsr.py is only ret = cell.value The None value should pass through here.
I made 2 changes in the file odsw.py:
I inserted after the columns = max([len(row) for row in to_write_data]) in the line 73 and 74 a if columns <1: return
It is because of empty sheets.
In the lines 60,61 I make the set_value only if not value_type == "nothing": so the function leave the cells empty, if the element in the list is None.

Here are the changed files:
changes.zip

The changes will work only thogether, so you have commit at the same time, and edit dependency.

best regards

Zsolt

Cannot write even a single row using 0.6.0

I'm using the following software:

$ sudo -H pip3 list | egrep 'ezodf|ods3'
ezodf                         0.3.2               
pyexcel-ezodf                 0.3.4               
pyexcel-ods3                  0.6.0       

I am unable to write even a single row without hitting an exception. Here is a test program:

#!/bin/env python3
from pyexcel_io import writer

FILENAME = 'tmp.ods'
LIBRARIES = ['pyexcel-ods', 'pyexcel-ods3', 'pyexcel-odsw']
LIBRARY = LIBRARIES[1]
ROW = ['c' + str(c) for c in range(153)]


with writer.Writer('ods', library=LIBRARY) as file_stream:
    file_stream.open(FILENAME)
    page_stream = file_stream.writer.create_sheet('mysheet')
    page_stream.write_row(ROW)

and the exception:

$ ./ods.py 
Traceback (most recent call last):
  File "./ods.py", line 13, in <module>
    page_stream.write_row(ROW)
  File "/usr/local/lib/python3.8/dist-packages/pyexcel_ods3/odsw.py", line 50, in write_row
    self.ods_sheet[self.current_row, count].set_value(
  File "/usr/local/lib/python3.8/dist-packages/ezodf/table.py", line 51, in __getitem__
    return self.get_cell(get_cell_index(key))
  File "/usr/local/lib/python3.8/dist-packages/ezodf/table.py", line 110, in get_cell
    return wrap(self._cellmatrix.get_cell(pos))
  File "/usr/local/lib/python3.8/dist-packages/ezodf/tablerowcontroller.py", line 40, in get_cell
    return self._rows[row][col]
  File "src/lxml/etree.pyx", line 1161, in lxml.etree._Element.__getitem__
IndexError: list index out of range

At the point of the exception, row is 0 and col is 10. Have I missed some setup step? Note that the real code for which this is a cut-down reproducer has to support xslx/csv/ods file formats and both xslx/csv seem to work fine.

Post install error

I tried to install pyexcel-ods(3).

When I try to run

from pyexcel_ods3 import get_data
data = get_data("Corretion_JBE_Mai_1S5.ods")
import json
print(json.dumps(data))

I have the error

File "/anaconda3/lib/python3.6/site-packages/odf/attrconverters.py", line 100, in cnv_family
raise ValueError( "'%s' not allowed" % str(arg))

ValueError: 'data-style' not allowed

What is the problem?

Saving sheets containing datetime objects to ods format

Hi,

I am new to pyexcel.
I try to save data to both xlsx and ods formats.
I have trouble when saving sheets containing datetime objects in ods format (actually, same problem with xls).
Things are OK with xlsx format.
See below a MWE and traceback

>>> import pyexcel, pyexcel_ods3, datetime
>>> data = [[datetime.datetime(2020, 1,1)]]
>>> sheet = pyexcel.Sheet(data)
>>> sheet.save_as('test.xlsx')           # This one is OK
>>> 
>>> sheet.save_as('test.ods')            # This one fails
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "/home/.../python3.8/site-packages/pyexcel/internal/meta.py", line 260, in save_as
    return save_sheet(self, file_name=filename, **keywords)
  File "/home/.../python3.8/site-packages/pyexcel/internal/core.py", line 48, in save_sheet
    return _save_any(a_source, sheet)
  File "/home/.../python3.8/site-packages/pyexcel/internal/core.py", line 60, in _save_any
    a_source.write_data(instance)
  File "/home/.../python3.8/site-packages/pyexcel/plugins/sources/file_output.py", line 31, in write_data
    self._renderer.render_sheet_to_file(
  File "/home/.../python3.8/site-packages/pyexcel/plugins/renderers/excel.py", line 28, in render_sheet_to_file
    save_data(file_name, data, **keywords)
  File "/home/.../python3.8/site-packages/pyexcel_io/io.py", line 143, in save_data
    writer.write(to_store)
  File "/home/.../python3.8/site-packages/pyexcel_io/writer.py", line 42, in write
    self.writer.write(incoming_dict)
  File "/home/.../python3.8/site-packages/pyexcel_io/plugin_api/abstract_writer.py", line 12, in write
    sheet_writer.write_array(incoming_dict[sheet_name])
  File "/home/.../python3.8/site-packages/pyexcel_ods3/odsw.py", line 66, in write_array
    self.write_row(row)
  File "/home/.../python3.8/site-packages/pyexcel_ods3/odsw.py", line 38, in write_row
    value_type = service.ODS_WRITE_FORMAT_COVERSION[type(cell)]
KeyError: <class 'datetime.datetime'>

Is that a bug or am I missing something?

Why is the key datetime.datetime missing from ODS_WRITE_FORMAT_COVERSION and the two others?

ODS_FORMAT_CONVERSION = {
    "float": float,
    "date": datetime.date,
    "time": datetime.time,
    "timedelta": datetime.timedelta,
    "boolean": bool,
    "percentage": float,
    "currency": float,
}

ODS_WRITE_FORMAT_COVERSION = {
    float: "float",
    int: "float",
    str: "string",
    datetime.date: "date",
    datetime.time: "time",
    datetime.timedelta: "timedelta",
    bool: "boolean",
}

VALUE_CONVERTERS = {
    "float": float_value,
    "date": date_value,
    "time": time_value,
    "timedelta": time_value,
    "boolean": boolean_value,
    "percentage": float_value,
}

Thank you.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.