image

Не так давно я опубликовал маленькую заметку о небольшой программе, которую я разработал для приятеля. К моему удивлению, она получила неплохие отзывы и «пришлась ко двору» некоторым «хабровчанам».

Я подумал и решил поделиться ссылками на другие свои «крохотульки», маленькие разработки, опубликованные open source. Number #2 будет небольшая программа-шутка, превращающая картинку в формате jpeg в Excel spreadsheet ;)

Идея данной программы-шутки родилась в процессе «пивной вечеринки» с друзьями-программистами. Речь зашла о нестандартных форматах хранения изображений; после обсуждения идеи хранения изображения (или любого «бинарника») в двоичном формате в виде распечатанного на лазерном или струйном принтере листе бумаги, с последующим сканированием и распознаванием, мне пришла в голову мысль об использовании фонового цвета ячеек таблицы Excel.

Сказано — сделано, реализация заняла чуть больше времени, нежели «гугление» работы с MS Excel. Программка не оптимизированна, работает достаточно медленно (потому, что рисует pixel by pixel), обрабатывает только jpeg формат. Я уверен, что умельцы — знатоки работы с MS Excel, смогут ускорить ее в разы (но, прежде чем заняться этим, подумайте — нужно ли? Ведь смысла и пользы от данной программки практически ноль!).

Саму программку, и ее простейший исходный код, вы можете скачать с Codeplex-а. Таблицу Excel, содержащую фотографию милой девушки (спасибо, гугл!) в заголовке, можно скачать вот тут (вирусов нет!).

Быть может, исходный код данной программки поможет кому-то в освоении взаимодействия с MS Excel из C#, ну, или просто даст вам небольшой повод улыбнуться, и вспомнить, что в нашей интереснейшей профессии всегда остается время для «нашенского», специфического юмора и шуток :)
Поделиться с друзьями
-->

Комментарии (37)


  1. leremin
    22.01.2017 10:25
    +1

    Interop вроде же устаревший моветон? Open XML наше все. И работает быстрее на несколько порядков.


    1. sens_boston
      22.01.2017 10:30

      Уважаемый leremin, если Вам не лень — то «пример в студию» (благо open source). Сам с удовольствием поучусь — вдруг где-нибудь, да пригодится…


      1. leremin
        22.01.2017 10:43
        +1

        Честно, лень. Но вечером может напишу тоже самое на OpenXML и выложу. Там идея в том, что в Interop вы фактически эмулируете действия пользователя, которые обрабатываются Excel, а в случае OpenXML — вы просто создаете XML документ, т.е. хоть в 100 потоков на кластере это можно делать. Отсюда и скорость, нет накладных расходов на обработку событий в Excel.

        А по существу вопроса, в комплекте OpenXML SDK есть программа, которая по xlsx файлу может получить исходник на C#, который создаст этот документ. Да, там код адски перегружен, но учился я так.


        1. sens_boston
          22.01.2017 10:53

          Когда-то, давным давно, у меня была задача достаточно оперативно передавать в Excel довольно большие объемы достаточно часто (2.5 Msp ADC PCI board), и я с ней справился. Правда, тогда был задействован C++ (или C-шный) «bridge», native API Excel-а. Работало достаточно «живенько», считало средствами Excel FFT в real time практически, и было очень востребовано «непродвинутыми» учеными (которым чем проще, тем лучше).

          В этой крохотной программке я столкнулся с тем, что иначе, чем «попиксельно» (cell by cell) не получается, подробностей, к сожалению, не помню.

          Поскольку я в этой области на «искперта» ну никак не претендую, буду рад увидеть мастер-класс от вас, чисто ради интереса.


          1. leremin
            22.01.2017 11:29
            +1

            Вечером, возможно, не до этого. Но надо понимать, что Interop и OpenXML — это две большие разницы. В первом случае вы работаете с Word/Excel/PowerPoint, а во-втором — с xml иерархией. Например, для автоподбора ширины столбцов в таблице — нужно нажать одну кнопку в Word, соответственно — один метод в Interop. А в OpenXML вы должны будете этот метод сами реализовать, т.е. посчитать оптимальную ширину и задать всем столбцам.

            Я тоже не эксперт, но и Interop можно сильно ускорить, нужно минимизировать количество вызовов методов. Например, сгенирировать текстовый файл средствами C# и импортировать его в книгу средствами Excel вместо того, чтобы заполнять ячейки в цикле Но в данном случае это не то.


            1. sens_boston
              22.01.2017 11:40

              Ну, попробуйте, спортивного интереса ради, ведь за язык вас никто не тянул ;) Я прекрасно понимаю, как устроен OpenXML, да и любой, не имеющий представления, может переименовать ,xlsx файл в .zip, открыть через архиватор/Far и посмотреть, что внутри архива.


              1. leremin
                22.01.2017 13:51

                Написано ужасно, но картинку 1024x1024 сконвертировал в xlsx за 9 секунд.


              1. MnogoBukv
                22.01.2017 17:02
                +2

                Зачем переименовывать? Ctrl+PgDn


              1. leremin
                22.01.2017 19:14

                Там ошибка с индексами стиля была. Вот так вроде без артефактов рисуется.


                1. sens_boston
                  22.01.2017 20:28

                  Спасибо, идея понятна, только у вас код с ошибкой — крешится на не квадратных картинках (но для простоты и так сойдет), и результат для изображения 1024x1024 не открывается в MS Excel.


                  1. leremin
                    22.01.2017 20:33

                    Может быть, я это написал на коленке. И половину времени гуглил, как цвет ячейки задать — никогда не приходилось.


                    1. sens_boston
                      22.01.2017 20:49

                      Да понятно, я без претензий (собственно, это и было одним из «условий» «задачи» — чтобы «на коленке и не напрягаясь»). Действительно, через OpenXml намного быстрее, по понятным причинам (через interop могло бы быть тоже быстро, если бы можно было задавать цвета Range-ем — но тогда что-то не получилось с этим).

                      Непонятно только, почему Excel ругается на большие «картинки»-таблицы. Вы в Excel-е проверяли, или только в Open Office?


                      1. leremin
                        22.01.2017 21:01

                        Открывал только в Excel 2016.


                        1. sens_boston
                          22.01.2017 22:27

                          Угу, я именно в Excel 2016 и пробовал. А вот результат обработки 512x512 открывается отлично. Ну да это мелочи, фиг с ним, непринципиально.

                          Довольно удобно работать через OpenXml; добавлю в «копилку», на случай, если придется столкнуться. Спасибо за хорошую идею!


                      1. namwen
                        23.01.2017 17:34

                        leremin имплеменировал non-SAX style (думаю, кто работает с XML знаком термин), если перейти на него + немного пооптимизировать, то получится в разы быстрее, выйти на время <1 сек вполне реально, попробую поучаствовать в челлендже вечерком.

                        К примеру, у нас на сервере задача генерировать >1M записей таблицы (без формул, чисто репорты) с минимальным потреблением памяти и максимальной производительностью. На простеньком i7 devstation OpenXML (SAX) дает ~600k cells per second (1М ячеек где-то за ~1.6 секунды).


              1. leremin
                22.01.2017 19:26

                Интересно, что на больших файлах Excel ругается на стили: 128x128 открывается, 256x256 — уже нет. Надо будет посмотреть что там в вашем случае.


                1. LoadRunner
                  23.01.2017 09:04

                  Может не проходит по каким-то из ограничений?
                  Там для Excel 2013\2016 ограничение на 64000 уникальных стиля ячейки. А 256х256 — это несколько больше уже. И тут уже надо оптимизировать — создавать таблицу стилей и привязывать к ячейке строго определённые, чтобы не выходить за пределы.


                  1. leremin
                    23.01.2017 09:52

                    Но цветов-то меньше. Я дубликаты цветов убирал, но вообще — да, скорее всего что-то такое и есть.


                    1. LoadRunner
                      23.01.2017 10:56

                      Мне кажется, когда к каждой ячейке применяют форматирование отдельно, пусть даже одинаковое — это всё равно считается за уникальный стиль. Применять надо диапазонами, скорее всего.

                      Предлагаю потестировать на одноцветном изображении — когда каждой ячейке индивидуально присваивается цвет и когда на весь диапазон он применяется.


            1. d-stream
              22.01.2017 17:02

              Ну можно в части случаев совместить подходы: заполнять OpenXML, а потом украшать/форматировать — Interop

              Кстати был еще и третий вариант — плевать из clipboard (понятно, что с кучей оговорок, нюансов и ограничений)…


              1. leremin
                22.01.2017 17:20

                Ну на практике я их и комбинирую. Если нужно бланк заполнить, то естественно проще сбацать шаблон и по закладкам вставить нужный текст через Interop, например.


  1. Katsuko
    22.01.2017 10:29

    Про пользу это вы зря.) Возможно кому нибудь нужно будет руками экспортировать данные в xsl(x) в изображениями


  1. sens_boston
    22.01.2017 11:18

    Что любопытно: проверил линк из статьи на демонстрационный xlsx, который открывается через online-овый Excel — очень любопытно Microsoft отрисовывает ;) Даже на моем Lumia 950 получается гораздо быстрее. Вот так, получился неплохой тестовый case для MS ;)

    Очень интересно наблюдать, в какой последовательности отрисовываются/рендерятся ячейки таблицы! Если при работе моей программки все понятно, то в случае MS я оказался в затруднении, честное слово…


    1. sens_boston
      22.01.2017 11:56

      Wow, что еще любопытнее, так это то, что Chrome отрисовывает все (хотя и по странной логике программистов MS, и довольно медленно), Firefox гордо пытается, но в конце практически «сдыхает», а IE и Edge тупо рендерят какую-то фигню с «мусором», после чего тупо «отваливаются» ;)


      1. ARad
        22.01.2017 12:22

        У меня FF нормально отрисовал


    1. alias1923
      22.01.2017 17:07
      +2

      LibreOffice 5.0 начал открывать, ушел в себя и не вернулся


      1. Yuego
        22.01.2017 20:35

        Эх… Несколько минут назад попытался открыть файлик в OpenOffice и LibreOffice.
        Всё ещё жду результата. Каждый забрал себе целиком по ядру процессора и активно прогревают воздух в комнате.
        Если всё-таки откроется, хочу попробовать пересохранить в ODT и открыть снова :)


        1. xkorolx
          23.01.2017 13:11

          Пользуйтесь ONLYOFFICE). И десктоп и онлайн открывает запросто)


          1. Yuego
            23.01.2017 18:15

            Я таки открыл и в Либре и в Опен.
            Первый даже смог отобразить фото, второй — только серый фон.
            Либре изрядно тормозил и зависал.
            Сохранил в ODT — открывает чуть быстрее, но так же тормозит.

            За предложение спасибо, но меня либре вполне устраивает.


  1. Jeditobe
    22.01.2017 16:11
    +5

    А еще можно яичеки заполнить текстом того же цвета, что и заполнение. Получится стеганография.


    1. oisee
      22.01.2017 19:43
      +2

      яичеки

      С этим, возможно, получится не только стегано-


  1. AlexALX
    22.01.2017 18:18

    Хехе, мне данная статья напомнила о моих потугах с рисованием BMP файла в html5 canvas попиксельно (через js), гдето даже код валяется))


    1. leremin
      22.01.2017 19:16

      По-моему через это в том или ином виде прошли почти все.


  1. kanikeev
    22.01.2017 21:59

    Не умеет правильно считать пропорции :(
    попробуйте фотку 2x3


  1. 776166
    22.01.2017 22:19

    MInecraft — это плохо.


  1. LoadRunner
    23.01.2017 09:08
    +2

    Не дай бог это попадёт к бухгалтерам. Пусть лучше в Word картинки вставляют.


  1. Azmadan
    23.01.2017 17:37

    Вариант когда заказчик, который задерживает выплату, просит выслать исходники таблицы в электронном виде:
    1. Из экселя делаем принтсрин или печатаем на виртуальный принтер в виде картинки
    2. Конвертируем картинку таблицы с помощью программы автора в эксель в «удобном» для редактирования виде.
    3. Ждем выплат >:$